Reputation: 123
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
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