How to pause any coroutine according to your global pause state :

Discussion in 'Scripting' started by n0mad, Nov 23, 2010.

  1. n0mad


    Jan 27, 2009

    as coroutines are very important in optimization processes, making them compatible with a game paused state could be vital.

    So here we go :

    In your class containing those coroutines (or in any abstract/singleton you want), put these functions :

    Code (csharp):
    1. public Coroutine _sync(){
    2.         return StartCoroutine(PauseRoutine())
    3.     }
    5. public IEnumerator PauseRoutine(){
    6.         while (_myPauseState) {
    7.             yield return new WaitForFixedUpdate()
    8.         }
    9.         yield return new WaitForEndOfFrame();  
    10.     }
    with _myPauseState being your global pause state.

    then in any Coroutines, put this at the end (or at any place you want to check for a pause) :

    Code (csharp):
    1. yield return _sync();

    I personally prefer to put the first code block into a generic baseClass, derived from MonoBehaviour , and then derive all my other "pause-able" classes from it. So I don't have to rewrite the block in all the new pause-able classes.
  2. _joe_


    Nov 14, 2012
    Just wanted to say thank! Great script!
  3. Sherlock-jr


    Oct 2, 2014
    What if i want to pause a coroutine that has a "yield return new WaitForSeconds(3);"?
    Where should i call to "yield return _sync();"?
  4. lordofduct


    Oct 3, 2011
    I'm not sure if they're going to respond 4.5 years later...

    Personally I don't use unity Coroutines, and instead I have my own 'RadicalCoroutine' that wraps around the unity Coroutine.

    One feature of it is controlling how the coroutine pauses when the MonoBehaviour/GameObject it was called with gets enabled/disabled or activated/deactivated.

    Here is the manager for said radicalcoroutines pausing:

    It automatically gets added to the GameObject if you create a coroutine that behaves unlike the default behaviour. As you can see in the RadicalCoroutine itself:

    Then in code, when you start a RadicalCoroutine you can say something like:

    Code (csharp):
    2. this.StartRadicalCoroutine(this.MyRoutine(), RadicalCoroutineDisableMode.Pauses);
    What I usually do is I have a game state machine that will disable any critical gameobjects that get paused during 'pause' mode.

    Now, with all that... you may notice in the Start/Resume methods, it checks the most recent 'IRadicalYieldInstruction' and pauses/unpauses it.

    Basically what I did was create a 'WaitForDuration' yield instruction:

    This mimics the behaviour of 'WaitForSeconds', BUT is pausible (and also scalable, using ITimeSupplier, which is something else I have in my framework). If you yield a WaitForDuration, or yield a WaitForSeconds in a coroutine that is pausible which then gets converted to a WaitForDuration, and the coroutine gets paused. This WaitForDuration doesn't count time for the duration of that pause.
    Last edited: Apr 9, 2015
    ThermalFusion likes this.