Search Unity

Is it possible to have a coroutine exit WITHOUT waiting for the next frame?

Discussion in 'Scripting' started by tmcsweeney, Nov 17, 2011.

  1. tmcsweeney

    tmcsweeney

    Joined:
    May 24, 2011
    Posts:
    20
    I've got a complex asynchronous process that runs in a coroutine, sprinkled throughout it are checks to see if has taken up too much of the current frame, and if it has it yields until the next frame, so far so good.

    Code (csharp):
    1.  
    2.     void Start()
    3.     {
    4.         StartCoroutine(ComplexProcess());
    5.     }
    6.  
    7.  
    8.     System.Collections.IEnumerator ComplexProcess()
    9.     {
    10.         //do stuff
    11.         if(TooMuchTime()) yield return null;
    12.  
    13.         //do more stuff
    14.         if(TooMuchTime()) yield return null;
    15.    
    16.         //etc
    17.     }
    18.  
    However my coroutine needs to call other complex functions that usually (but not always) take up lots of time, so within ComplexProcess() I use:
    Code (csharp):
    1. yield return StartCoroutine(SomeComplexSubProcess);
    and do the same time checks within the sub-process.

    This all works fine as long as the sub process is taking a relatively long time and is yielding several times. However if the SubProcess discovers that it has very little work to do then we don't want to yield for a frame but rather carry on with the parent coroutine. I can't work out how to exit from the child in a way that will allow the parent coroutine to continue running in the current frame.
    yield return null; yield break; and simply falling out the bottom of the coroutine function all cause the system to wait until the next frame before continuing, which means that a process that should take a couple of frames ends up taking hundreds or thousands of frames if the sub-coroutine is being called lots and lots of times very quickly.

    Is there a way to do this with the standard unity coroutines, or am I asking to much of them?

    I'm aware of this: http://www.unifycommunity.com/wiki/index.php?title=CoroutineScheduler although it looks like it suffers from the same problem I can see how it would be easily adapted by changing the
    Code (csharp):
    1. UpdateAllCoroutines()
    method to keep looping through the list of active coroutines until they are all idle.

    Thanks in advance
    Tim
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It does sound like you're trying to make coroutines do things they're not intended for, and that you'd be much better off with threads.

    --Eric
     
  3. tmcsweeney

    tmcsweeney

    Joined:
    May 24, 2011
    Posts:
    20
    <sigh> threads is where I started out, but some of the processes need to interact with Unity, so I hit a brick wall there.

    One of my backlog tasks is to separate out the parts of the process that are parallelisable AND don't require interacting with unity and move them to a thread pool to speed things up on multi-core machines.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Even on machines that don't have multiple cores, threads will eliminate the "TooMuchTime" hacks, but I expect you already know that.

    --Eric