I just started using Unity and I want to build the following function: Currently I press a button which spawns an asteroid outside of the screen, then the asteroid moves through the screen from right to left and finally I destroy the asteroid out of screen. All this is working already. But now I want to change the button function so that it spawns more asteroids delayed by a few seconds. And I don't know how to do that. My Code looks like this at the moment:
public class ButtonSkript : MonoBehaviour
{
private Vector3 spawnPosition = new Vector3(15, 0, 0);
public GameObject planet_001Prefab;
public GameObject planet_011Prefab; // not in use
public GameObject planet_017Prefab; // not in use
public GameObject planet_079Prefab; // not in use
public void ShowJourney()
{
int[] asteroids_array = {27, 569, 1293, 37};
int[] material_type_array = {0, 2, 1, 3}; // not in use
for (int i = 0; i < asteroids_array.Length; i++) {
GameObject a = Instantiate(planet_001Prefab);
a.transform.position = spawnPosition;
Destroy(a, 3);
// wait for 3 seconds
}
}
}
public class Translate : MonoBehaviour
{
public float speed = 10.0f;
// Update is called once per frame
void Update()
{
moveAsteroid(new Vector2(-1, 0));
}
void moveAsteroid(Vector2 direction)
{
transform.Translate(direction * speed * Time.deltaTime);
}
}
I already tried System.Threading.Thread.Sleep(3000);
and I also tryed to build a timer with IEnumarate
and yield return new waitForSeconds(3.0f);
but both things are not working or I didn't implement it correctly.
It is probably an easy question, but I can't figure it out on my own.
Thanks for the help :)
The StartCoroutine
method is a little like a fire-and-forget method. It’ll start a new coroutine, without actually waiting to see what the coroutine is doing. So, your initial attempt at looping through and starting ‘n’ coroutines is doing exactly that - starting 4 new coroutines all at the same time.
A potential fix in this situation might be:
int[] asteroids_array = {27, 569, 1293, 37};
int[] material_type_array = {0, 2, 1, 3}; // not in use
public void ShowJourney()
{
StartCoroutine(Spawn());
}
IEnumerator Spawn()
{
for (int i = 0; i < asteroids_array.Length; i++)
{
var a = Instantiate(planet_001Prefab);
a.transform.position = spawnPosition;
Destroy(a, 3); // could be here, or after the WaitForSeconds.
yield return new WaitForSeconds(3);
}
}
Note that there’s no check to see if the coroutine is running, so if you have a button attached to ShowJourney
you might still end up with lots of coroutines running.
If each asteroid followed your logic, you could also just reposition the asteroid instead of creating a new one. For example:
IEnumerator Spawn()
{
var a = Instantiate(planet_001Prefab);
a.transform.position = spawnPosition;
for (int i = 0; i < asteroids_array.Length; i++)
{
yield return new WaitForSeconds(3);
a.transform.position = spawnPosition;
}
Destroy(a);
}
But this just illustrates that there’s often many ways to accomplish the outcome you’re looking for.