Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // There are a couple different ways to use coroutines in Unity, though some are worse
- // than others. Here is the pattern that I've been using which I find to be pretty clean
- // and flexible.
- // First, we'll always use an IEnumerator variable to be able to refer to individual
- // instances of a coroutine. Often times it makes sense to pack these variables into some
- // collection if you'll need multiple instances at once, or to make them a member of a
- // class/struct.
- IEnumerator thingyCoroutine;
- // Next we can define our coroutine behavior. The trick here is that we'll set
- // thingyCoroutine to null whenever the coroutine exits normally. This way, we can keep
- // track of the status of the coroutine without additional flags.
- IEnumerator Thingy() {
- while (doStuff) {
- yield return null;
- if (badThing) {
- // The main thing you'll have to remember with this pattern: whenever you end
- // the coroutine, you need to make sure to set thingyCoroutine to null.
- thingyCoroutine = null;
- yield break;
- }
- }
- thingyCoroutine = null; // Again, we must set this to null when exiting the coroutine.
- }
- // Now we can create a public interface that handles starting/stopping the coroutine
- // gracefully.
- public void StartThingy() {
- // We can see if the coroutine is already running first. Common things to do here are
- // to return or to stop the coroutine and possibly do some clean up before restarting.
- if (thingyCoroutine != null) { return; }
- thingyCoroutine = Thingy();
- StartCoroutine(thingyCoroutine);
- }
- public void StopThingy() {
- if (thingyCoroutine == null) { return; }
- StopCoroutine(thingyCoroutine);
- thingyCoroutine = null;
- // Anything else you need to do to exit gracefully can go here, e.g. resetting the
- // things the coroutine may have changed.
- }
- public void RestartThingy() {
- StopThingy();
- StartThingy();
- }
- // When a MonoBehaviour is disabled, all coroutines running on it are stopped at their
- // next yield instruction. If you don't want this, you can start the coroutines on some
- // behaviour that you know won't be disabled. Perhaps you have some singleton, e.g.
- // Game.instance.StartCoroutine(thingyCoroutine).
- // Otherwise, since we know thingyCoroutine will only be null when we stopped it
- // ourselves, we can restart any coroutines that didn't finish in OnEnable.
- void OnEnable() {
- if (thingyCoroutine != null)
- StartCoroutine(thingyCoroutine); // Pick up where we left off
- }
- void OnDisable() {
- if (gameObject.activeInHierarchy) {
- // Bonus gotcha: OnDisable is also called when an object is being destroyed,
- // except in this case the gameObject will be active when it's being destroyed and
- // inactive when it's being disabled as normal. You may need to handle things
- // differently in this situation, and this is the only way to check for it AFAIK.
- }
- // Sometimes you may want to exit gracefully instead of picking up where we left off
- // when the behaviour is re-enabled.
- if (badThing)
- StopThingy();
- }
- // Having this IEnumerator variable makes it easy for us to inquire about the state of the
- // coroutine. Sometimes it's helpful to have these sorts of fields if other parts of the
- // game need to know about the routine, e.g. if another coroutine kicks off this routine
- // and needs to wait until it's finished.
- public bool ThingyIsRunning { get { return thingyCoroutine != null && gameObject.activeInHierarchy; } }
- public bool ThingyIsPaused { get { return thingyCoroutine != null && !gameObject.activeInHierarchy; } }
- public bool ThingyStarted { get { return thingyCoroutine != null; } }
- public bool ThingyStopped { get { return thingyCoroutine == null; } }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement