AaySquare
AaySquare

Reputation: 123

How to spawn a set number of random cubes together and after these cubes disappear, spawn another set of cubes in Unity?

Currently my scene spawns one cube at a time at a specific spawn rate. So after every 5 seconds, a new cube spawns and it slowly fades away and disappears after a short time.

However, I now want to make it so that for example 5 cubes spawn together and once they all disappear, I want new 5 cubes to spawn.

Probably just a simple change I need to do for this but I really can't figure it out.

Here is my code so far but not sure where to go about from here on:

    public GameObject smallCubePrefab;
    public float rateOfSpawn = 1;
    private float nextSpawn = 0;

    List<GameObject> cubesList;

    // Update is called once per frame
    void Update()
    {
        // Spawn new cubes at specified spawn rate
        if (Time.time > nextSpawn)
        {
            nextSpawn = Time.time + rateOfSpawn;
            StartCoroutine(SpawnAndFadeOutCube());
        }
    }

    public List<GameObject> GenerateCubes()
    {
        // Create an empty list of cubes
        cubesList = new List<GameObject>();

        // Spawn cube at random position within the big cube's transform position
        Vector3 randPosition = new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f));

        // Generate higher chance (2 chances in 3) of spawning small cubes with offset = 0 on Y-axis 
        List<float> randomY = new List<float>() {0, 0, Random.Range(-1f, 1f)};
        randPosition.y = randomY[Random.Range(0, 3)];
        randPosition = transform.TransformPoint(randPosition * .5f);

        // Spawn small cube
        GameObject smallCube = Instantiate(smallCubePrefab, randPosition, transform.rotation);

        // Give random color
        smallCube.GetComponent<Renderer>().material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);

        // Give random size
        int randSize = Random.Range(1, 10);
        smallCube.transform.localScale = new Vector3(randSize, randSize, randSize);

        // Add spawned cube to the list of cubes
        cubesList.Add(smallCube);

        return cubesList;
    }

    public IEnumerator SpawnAndFadeOutCube()
    {
        // Give random lifetime
        float fadeSpeed = Random.Range(0.01f, 0.05f);
 
        List<GameObject> smallCubes = GenerateCubes();

        foreach (GameObject cube in smallCubes)
        {
            while (cube.GetComponent<Renderer>().material.color.a > 0)
            {
                Color cubeColor = cube.GetComponent<Renderer>().material.color;
                float fadeAmount = cubeColor.a - (fadeSpeed * Time.deltaTime);

                cubeColor = new Color(cubeColor.r, cubeColor.g, cubeColor.b, fadeAmount);
                cube.GetComponent<Renderer>().material.color = cubeColor;
                yield return null;
            }

            Destroy(cube);
        }
    }

Upvotes: 1

Views: 586

Answers (1)

derHugo
derHugo

Reputation: 90901

Currently you spawn only a single cube and add it to a new list. Later you fade out all cubes (currently only one) at once with the same fade duration.

To me it sounds like you would rather want different fade durations for each cube.

I would rather split it up and have one Coroutine for each individual cube.

Also there is no need to create a new list everytime. In contrary, rather keep the existing list and only add and remove items. This way you can directly also use the list and check whether the cube you are removing is the last one and in that case initiate a new group spawn.

something like this

// Use the correct type for the prefab so you don't need GetComponent at all
public Renderer smallCubePrefab;

// How many cubes shall be spawned min/max randomly?
public int minCubes = 1;
public int maxCubes = 10;

// Create this list only ONCE
// Later simply add spawned cubes and remove the destroyed ones
// => Trigger a new group spawn if the list is empty
private readonly List<Renderer> cubesList = new List<Renderer>();

private void Start()
{
    // Trigger initial group spawn
    SpawnCubes();
}

private void SpawnCubes()
{
    // Pick random amoun
    // +1 since upper parameter is exclusive for int
    var amount = Random.Range(minCubes, maxCubes + 1);

    // Start individual Coroutine for each cube
    for(var i = 0; i < amount; i++)
    {
        StartCoroutine (SpawnAnsFadeoutCube());
    }
}

// This spawns 1 single cube and adds it to the existing list 
private Renderer GenerateCube()
{
    // Spawn cube at random position within the big cube's transform position
    var randPosition = new Vector3(Random.Range(-0.5f, 0.5f), 0, Random.Range(-0.5f, 0.5f));

    // Generate higher chance (2 chances in 3) of spawning small cubes with offset = 0 on Y-axis 
    var randomY = new List<float>() {0, 0, Random.Range(-0.5f, 0.5f)};
    randPosition.y = randomY[Random.Range(0, 3)];
    randPosition = transform.TransformPoint(randPosition);

    // Spawn small cube
    // Will return Renderer since the prefab is now of type Renderer
    var smallCube = Instantiate(smallCubePrefab, randPosition, transform.rotation);

    // Give random color
    smallCube.material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);

    // Give random size
    var randSize = Random.Range(1, 10);
    smallCube.transform.localScale = Vector3.one * randSize;

    // Add spawned cube to the list of cubes
    cubesList.Add(smallCube);

    return smallCube;
}

private IEnumerator SpawnAndFadeOutCube()
{
    // Give random lifetime
    var fadeSpeed = Random.Range(0.01f, 0.05f);

    var cube = GenerateCube();
    var material = cube.material;
  
    // This routine is only responsible for this single cube!  
    while (material.color.a > 0)
    {
        var cubeColor = material.color;
        var fadeAmount = cubeColor.a - (fadeSpeed * Time.deltaTime);

        cubeColor.a = fadeAmount);
        material.color = cubeColor;

        yield return null;
    }

    
    cubesList.Remove(cube);
    Destroy(cube.gameObject);
    
    // Was this the last cube? 
    if(cubeList.Count == 0)
    {
        // Trigger next group spawn
        SpawnCubes();
    }
}

Upvotes: 1

Related Questions