Wait till repsawn

Hey! :slight_smile:

I’ve got a little problem in here. I need my game to wait some time before spawning another object (again at the same place).

I’ve tried System.Threading.Thred.Sleep(2000), but it freezed whole game for 2 sec.

There is a code:

using UnityEngine;
using System.Collections;

public class kolize : MonoBehaviour {

    private float HP = 10f;

    void OnCollisionEnter(Collision collision) {
        Destroy(collision.gameObject);
        HP -= promenneMaleRakety.damage;
        if(HP <= 0)
        {
            Destroy(gameObject);
          
            //wait code here!!
          
            Instantiate(gameObject);
        }
    }
}

Thanks :slight_smile:

You want a Coroutine!

IEnumerator SomeCoroutine() {
Debug.Log("Doing a thing");
yield return null;
Debug.Log("Doing a thing on the next frame");
yield return new WaitForSeconds(2f);
Debug.Log("Doing a thing two seconds later!");
}

// in OnCollisionEnter:
StartCoroutine(SomeCoroutine());

BUT

You’re going to run into two problems:

  1. an inactive or destroyed object can’t run coroutines, and you’re destroying the object you’re running this code on. Solution: Put this on a manager class instead, which watches the… uh… the “kolize”. When the kolize is null (when the object has been destroyed), it starts the coroutine.

  2. You can’t instantiate a destroyed object, and you’re destroying the object before you instantiate it.
    Solution: Make the object a prefab, instantiate that instead.

Got a problem in here. When I write IEnumerator SomeCoroutine, the code won’t make it threw yield return new WaitForSeconds(2f), it won’t even go threw yield return null.

Any idea?

Did you call it using StartCoroutine?

Yeah, look…, debug messages me only - Doing a thing

using UnityEngine;
using System.Collections;

public class kolize : MonoBehaviour {

    private float HP = 10f;

    IEnumerator SomeCoroutine() {
        Debug.Log("Doing a thing");
        yield return null;
        Debug.Log("Doing a thing on the next frame");
        yield return new WaitForSeconds(2f);
        Debug.Log("Doing a thing two seconds later!");
    }

    void OnCollisionEnter(Collision collision) {
        Destroy(collision.gameObject);
        HP -= promenneMaleRakety.damage;
        if(HP <= 0)
        {
            StartCoroutine(SomeCoroutine());

            Destroy(gameObject);

        }
    }
}

You’re destroying the gameObject immediately when you start the coroutine - coroutines don’t run on destroyed objects.

I’m totally lost. Can you help me with the code please? :confused:

Reread my first reply. If you have specific questions about those suggestions or things you don’t understand, I can answer those.

Ok. I’m not sure if i understood this : Put this on a manager class instead, which watches the… uh… the “kolize”.
Don’t know what manager class means…

OK. A manager class basically means that there is a third-party overseer - it manages other objects without being affected itself. Most developers make a “GameRunner” or something like that. There’s nothing special about this object in the engine - it’s just an object with a script attached - it just serves special functions.

In this case, you want the manager class to watch the “kolize” object. You’ll have “public kolize currentKolize;” (Feel free to change the names as you see fit), and in the inspector, you drag in your kolize object from the scene. Now, we wait:

void Update() {
if (currentKolize == null) {
StartCoroutine(WaitThenRespawn() );
}
}

WaitThenRespawn is a coroutine that waits for 2 seconds, and then instantiates a prefab. When it does, you’ll have to make sure you re-assign currentKolize to the component on the newly spawned object.

There is one issue with this that I just noticed while typing it (but I’m leaving it here for the teaching opportunity): for those two seconds, currentKolize will still be null, so it will keep starting new WaitThenRespawn coroutines running in parallel… and after two seconds, the coroutines will all start to end and you’ll be flooded with new kolize’s. So, I’m going to tweak that concept a bit into a “game cycle” type coroutine:

void Start() {
StartCoroutine(GameCycle() );
}
public kolize currentKolize;
public GameObject kolizePrefab;

IEnumerator GameCycle () {
while (true) { //if you ever have this line, MAKE SURE you have a yield, return, or break in the body, or you WILL freeze Unity!
yield return null;
if (currentKolize == null) {
yield return new WaitForSeconds(2f);
GameObject spawn = Instantiate(kolizePrefab) as GameObject;
currentKolize = spawn.GetComponent<kolize>();
}
}
}

The GameCycle coroutine is a straightforward way to write simple processes that loop in a sequence. Unlike Update which’ll get called every frame no matter what, the coroutine will only be running one thing at a time. And if that thing involves waiting, then everything will wait.