Search Unity

Destroying the object then restarting the scene

Discussion in 'Scripting' started by epochplus5, Jan 23, 2021.

  1. epochplus5

    epochplus5

    Joined:
    Apr 19, 2020
    Posts:
    677
    If the player blows up his own space station, it explodes and then breaks into a few pieces hurling through space.A mission failed message then pops up and i want the scene to restart after 5 seconds.
    I have a coroutine that times this and then restarts the level.

    But in the code after the explosion the game object gets destroyed, but then the coroutine doesnt run as the object is destroyed. What am i meant to do to destroy the object and then a few seconds later restart the level?
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Simply start the coroutine on an object that is not destroyed.
     
    Kurt-Dekker likes this.
  3. epochplus5

    epochplus5

    Joined:
    Apr 19, 2020
    Posts:
    677
    sorry but what is te principle behind that?
     
  4. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Not sure what you mean by "principle"...

    MonoBehaviours manage and update their coroutines for themselves. When they get destroyed or become inactive, they stop updating their coroutines.
     
  5. epochplus5

    epochplus5

    Joined:
    Apr 19, 2020
    Posts:
    677
    so do i move the coroutine to another script on another object? im sorry i dont understand what to do.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Hey Epoch, here's how it goes down. A coroutine is just an IEnumerator object, and you make one by just calling a coroutine.

    When you do that, nothing happens. It's like a water pump that needs to have its crank pumped, but nobody is pumping it so it sits there and does nothing.

    In Unity there's a special agreement: if you hand that IEnumerator object into StartCoroutine(), which is a method belonging to the object where that StartCoroutine() call is located, what Unity does is starts "pumping" that water pump for you, every frame, or waiting a bit, or whatever.

    Every time Unity "pumps" it, the code runs until the next
    yield
    statement. Based on what you yield, Unity will or will not pump it again, per the agreement.

    But the important part is that it is the MonoBehaviour where that StartCoroutine() is called that is running your coroutine. He's the only guy that knows about it. If he dies, so does your Coroutine. That's the ownership.

    There is nothing preventing you from sticking a little "stub" coroutine script on another object and tell that longer-lived script to run it for you.

    That structure in Unity is loosely called a "coroutine runner." Think of it as a handy motor sitting around waiting for water pumps and it will pump them for you.

    Here's an example: https://gist.github.com/LotteMakesStuff/d179d28f29bc9bb499dc5260e0146154

    I haven't used that one but to me it looks perfectly simple and awesome.

    Using the above code, you would use it by putting this in your script:

    Code (csharp):
    1. CoroutineRunner.RunCoroutine( MyOriginalCoroutine());
    That's it. This works beyond when your own script gets destroyed, BUT!!! Remember if your script does get destroyed while this coroutine is still running, if any part of the coroutine code touches any part the Destroyed GameObject, you'll get errors (such as if you try to move the gameObject where the coroutine is).

    But you can do static things like loading scenes after a few seconds, that's perfectly fine.
     
  7. epochplus5

    epochplus5

    Joined:
    Apr 19, 2020
    Posts:
    677
    I understand what you telling me about coroutines, i just cant work out how to implement it in this case.

    on my space station script if the armour runs out it runs a destroyed method.

    then after that method i have coroutine setup

    but how do i call that coroutine from another script? i mean how will that script know to call the coroutine when the station is blown up?

    Should the coroutine that delays time then restarts the level be on the space station script or another script on a different object. Really sorry im not understamding how this works.
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Any function or coroutine can accept a function or coroutine that it will run when it finishes.

    Broadly this is called a "callback" or "delegate" pattern.

    You are saying "Do your thing, and when you're done, do this next thing that you don't actually know anything about."

    Code (csharp):
    1. IEnumerator FirstCoRo( IEnumerator NextCoRo)
    2. {
    3.    // do some stuff, take some time, yield many frames, etc.
    4.    yield return null;
    5.  
    6.    // now start the next thing (whatever it is was passed into me)
    7.    CoroutineRunner.RunCoroutine( NextCoRo);
    8. }
    And to light that off you would:

    Code (csharp):
    1. CoroutineRunner.RunCoroutine( FirstCoRo( CoRoToCallAfterFirst()));
    It's like the rabbit hole in Alice in Wonderland... how deep would you like to go? It is an extremely powerful and flexible way of programming but it can blow your mind the first X times you get used to it.

    Using that coroutine runner above, something like:

    Code (csharp):
    1.  using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TestChainingStuffOnViaCoroutineRunner : MonoBehaviour
    6. {
    7.     void Start ()
    8.     {
    9.         CoroutineRunner.RunCoroutine( Step1( Step2()));
    10.     }
    11.  
    12.     IEnumerator Step1( IEnumerator Next)
    13.     {
    14.         Debug.Log( "Step1... start");
    15.         yield return new WaitForSeconds( 1.0f);
    16.         Debug.Log( "Step1... done");
    17.  
    18.         CoroutineRunner.RunCoroutine( Next);
    19.     }
    20.  
    21.     IEnumerator Step2()
    22.     {
    23.         Debug.Log( "Step2... start");
    24.         yield return new WaitForSeconds( 1.0f);
    25.         Debug.Log( "Step2... done");
    26.     }
    27. }
     
  9. epochplus5

    epochplus5

    Joined:
    Apr 19, 2020
    Posts:
    677
    I'm sorry, in this line:, CoroutineRunner.RunCoroutine( NextCoRo);
    where is CoroutineRunner coming from?

    Finding this very difficult, thanks for your patience.
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    That link above, the "lotte makes stuff" link!

    Get it working, go blow up lots of space stations... you can do it!