Search Unity

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

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

  1. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Hello,

    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.     }
    4.    
    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_

    _joe_

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

    Sherlock-jr

    Joined:
    Oct 2, 2014
    Posts:
    11
    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

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    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:
    https://code.google.com/p/spacepupp...unk/SpacepuppyBase/RadicalCoroutineManager.cs

    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:
    https://code.google.com/p/spacepupp...owse/trunk/SpacepuppyBase/RadicalCoroutine.cs

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

    Code (csharp):
    1.  
    2. this.StartRadicalCoroutine(this.MyRoutine(), RadicalCoroutineDisableMode.Pauses);
    3.  
    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:
    https://code.google.com/p/spacepupp...pacepuppyBase/IRadicalYieldInstruction.cs#252

    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.