2

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 :)

3
  • can you show the complete method? Commented Dec 29, 2022 at 15:30
  • i updated the post and it now includes the full method Commented Dec 29, 2022 at 15:46
  • A coroutine is your friend. Commented Dec 30, 2022 at 1:29

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much :) I tryed your code and it is working really well!
1

Trigger a Coroutine that yields for 3 seconds and then spawns the assets.

This will allow for execution to continue to compute the current frame while your coroutine runs in parallel.

Reference: https://docs.unity3d.com/Manual/Coroutines.html

key command: yield return new WaitForSeconds(3.0f);

4 Comments

I tryed your idea like this, but it is not working. it spawns all the asteroids on top of each other because the programm is not waiting. What did i do wrong? I added this method: ' IEnumerator Wait() { yield return new WaitForSeconds(3.0f); } ' and in the method in my question i added 'StartCoroutine(Wait());'
You need to put the code for spawning in the coroutine after your yield return... statement.
I tryed it like this: In the for-loop i only said for (int i = 0; i < asteroids_array.Length; i++) { StartCoroutine(Test()); } and then i call IEnumerator Test() { GameObject a = Instantiate(planet_001Prefab); a.transform.position = spawnPosition; Destroy(a, 3); yield return new WaitForSeconds(3.0f); } but the same problem as before. I spawn all 4 asteroids for all 4 elements in my array at the same time.
@SeanMiller - Please show the OP the correct code in your answer.
0

You can create an async method and wait 3 seconds for each iteration.

Your method will look like this`

public async  Task 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);

        await Task.Delay(3);
    }

1 Comment

I think this is a good idea, but it stills spawns 4 asteroids at the same time and is not waiting. And to run it, I needed to change the head of the method to public async void ShowJourney() instead of public async Task ShowJourney().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.