This article is too messy, recommended Frankjfwang: Comprehensive analytical coroutine Technology
The coroutine of unity is achieved through yield expression. This code is seen everywhere in the official script.
Questions:
What yield is.
What Coroutine is.
Unity's Coroutine program execution process is so strange.
Unity in the coroutine principle is what, how to achieve.
The use of unity Coroutine need to pay attention to what problems.
Yield's program execution characteristics in several languages:
The yield in Lua is to make synergistic functions run-> hang and pass parameters to resume. Resume makes the cooperative function suspend-> run and pass parameters to the Synergy function.
C # yield Return/break is used in the function query collection generator inside the value (similar to iterative) return, and record the current scene, the next query from the last record of the yield field, continue to carry on, until the execution is gone, then exit the logic of the yield. The yield break terminates the yield iteration logic and jumps out.
Yieldimplementation:
1). Caller callsfunction
2). Caller Requestsitem Request an element on demand
3). Next itemreturned returns the requested element
4). Goto Step #2
Yield expression in Python, a function that has a yield becomes a generator, calling the function to return an iterator object, calling the next method with an iterator object (or calling the next method automatically in the loop) before executing the function, executing to the yield The expression is interrupted, returns the current value of the iterator, retains the scene, and the next call to next begins execution from the field and stops after the iteration. You can see that the yield in Python and the yield in C # are similar, used to create generators, break back the iterator values at execution time, and record the scene, next time from the field.
The unity of the yield is similar to the C#,python, because unity is based on the. NET Framework, and the unity script begins with Boo (a variant of Python). It's just that unity has more coroutine types of features, and Startcoroutine coroutine management classes. Startcoroutine not start a new thread, but instead open a collaborative program, the default unity all code in one line thread (http://answers.unity3d.com/questions/280597/ new-thread-vs-startcoroutine.html).
The principle of the Coroutine language level:
Two years ago, the coprocessor seemed to be a very advanced thing, and then most languages were more or less supporting the process. I'm more familiar with Python's Gevent,lua coroutine,go goroutine. In particular, LUA and go, the language itself supports the process. A coprocessor is also called a lightweight thread. Popular point is to define a lot of tasks, and then through a thread round to each task is executed, collaborative operation. The thing about it is that every time you run to a task, it can start from where the task was last interrupted. In our general impression, only the operating system when the thread is scheduled to do such things, carry out a variety of into the stack, save state. The coprocessor, in total, only runs in a thread, and if you use the system stack of the thread itself, it's already gone. So here, the realization is to use memory to simulate the operation of the stack. Concrete implementation, I think the complexity must be not small.
As we know, threads are lighter than processes, so generating one thread consumes less resources than processes, and context switches are more economical than processes. And the turndown thread is more lightweight, context switching is more rapid. So in server programming to give people unlimited imagination. Although a mainstream Web server is not currently in use. But the performance of the Web services developed by the go language has come to the fore.
Second, unity of the coroutine implementation of the phenomenon:
The first method:
Voidstart ()
{
Print ("Starting" +time.time)----------------------------------------1
Startcoroutine (Waitandprint (2));-------------------------------------2
Print ("Done" +time.time);-------------------------------------------3
}
IEnumerator Waitandprint (float waittime)
{
Yield return new waitforseconds (waittime);------------------------4
Print ("Waitandprint" + time.time)----------------------------------5
}
The code is executed in the order of 12435
Execution to the 4 coprocessor registers the event, control to the external thread; The external thread executes to 3; The event occurs, the program segmentation execution mechanism Goto to the coprocessor records the stack information to execute the 5 statement.
IEnumerator Start ()
{
Print ("Starting" +time.time)----------------------------------------1
Yield return Startcoroutine (Waitandprint (2.0F));------------------------2
Print ("Done" +time.time);------------------------------------------3
}
IEnumerator Waitandprint (float waittime)
{
Yield return new waitforseconds (waittime);----------------------------4
Print ("Waitandprint" + time.time)-----------------------------------------5
}
The code is executed in the order of 12453
Why? Such a strange way of execution.
Program execution to 4, execute yield return expression registration event surrender control to external, because external also want to surrender control to also need to execute yield return expression statement so will be back into the Waitandprint function then the current state of the next step execution so execution to 5, Yield return expression statement after completion of control completely surrendered, after the execution of 3, the root cause is yield return can not be directly nested after the need to follow an expression (event).
Third, the unity of the official documents on the interpretation of Coroutine:
Normal coroutine updates are run after Theupdate function returns. Acoroutine is a function this can suspend its execution (yield) until the givenyieldinstruction finishes. Different Uses of coroutines:
Yield The coroutine'll continue after all Update Functionshave been Calledon the next frame.
Yield Waitforseconds (2); Continueafter a specified time delay, after the all Update functions have been to called for Theframe.
Yield waitforfixedupdate (); Continue afterall Fixedupdate has been called on all scripts.
Yield wwwcontinue aftera WWW download has completed
Yield Startcoroutine (MyFunc); Chains the Coroutine, and the MyFunc coroutine to Completefirst.
C # to add the return keyword between yield coroutine.
Four, unity in the coroutine principle of speculation:
Virtual machine Segmentation execution mechanism, the same type of nested stack storage implementation serial execution:. NET virtual machines, in each frame loop, are entered sequentially into each compiler's predefined entry. For the coroutine type, the compiler needs to generate some code to send a message after the time specified by the Coroutine type or after the event is completed (the. NET's virtual machines are marked with function pointers to manage the scene and after each frame check time or event is satisfied in the process). Give the CPU all power to the yield interrupted field, or manage each coroutine by multiple management classes containing different coroutine iterators, each frame using a polymorphic check time or event to arrive with a coroutine subclass, Give the CPU all power to the scene where the Coroutine subclass is interrupted, and continue to execute from the yield after the interrupted code, thus forming the mechanism that we see a function can be executed in a segmented way.
For nested coroutine types, the serial execution rather than parallelism is possible. NET virtual machines for the same coroutine type stack storage, the top of the stack to implement the serial execution, if the outer layer does not use yield return, then not serial execution, but the parallel implementation. You can then explain the order of execution in the example above.
Schematic diagram:
See: http://www.richardfine.co.uk/2012/10/unity3d-monobehaviour-lifecycle/
In fact, yield waitforseconds/null/waitforendofframe are driven by the entire game while loop, yield just handing over control to the external main thread and Coroutine setting event suspend Coroutine ( Not a thread is just a segmented execution mechanism, when the event occurs (not the next frame to arrive, but in a fixed period of time before or after the update or after the render, more than will go to the next frame) into the code inside the process.
Five, unity in the use of coroutine need to pay attention to the problem:
1. Where to use and where not to use:
Yield coroutine must be invoked in a class that is monobehaviour or inherited from Monobehaviour. Yield can not be used in update or fixedupdate.
2. Open the co-process:
Startcoroutine (String methodname) and Startcoroutine (Ienumeratorroutine) can open a single thread,
Difference:
When you use a string as a parameter, you can only pass one parameter when you open the coprocessor, and the performance consumption will be much higher; Using IEnumerator as a parameter does not have this limitation.
3. Delete the coprocessor:
1. In Unity3d, use Stopcoroutine (stringmethodname) to terminate a collaborative program that Monobehaviour specifies a method name, using Stopallcoroutines () To terminate all the Monobehaviour that the program can terminate.
Including Startcoroutine (IEnumerator routine).
2. There is also a way to terminate the collaboration program, the Gameobject active property of the program is set to False, when the active is set again ture, the collaboration program will not open again;
Setting the enabled of the script for the collaboration program to false does not take effect.
Use differences in 4.js and C #:
Use yield return instead of yield in C #.
Yield (break) statements in C # must be in the IEnumerator type, the return type of the C # method is IEnumerator, and the return value such as (Eg:yield returns new Waitforseconds (2); or yield returnnull);
5. The coordination function returns the value and the parameter type, the combination design pattern:
The return type of the collaboration program is coroutine type. In Unity3d, the Coroutine class inherits from the Yieldinstruction, so the return type of the collaboration program can only be null, the number of frames to wait (frame), and the time to wait.
The parameters of the collaboration program cannot specify ref, out parameters. However, we often use a collaborative program when using the WWW class, because the parameter address (reference) cannot be passed in the collaboration program, and the object cannot be output.
This allows each download of a WWW object to rewrite a collaborative program, the way to solve this problem is to build a WWW-based class (in combination with the model to solve-in fact, is not through the function of the global association of the object), and implement a download method. As follows:
Using Unityengine;
Using System.Collections;
public class Wwwobject:monobehaviour
{
public www www;
Public wwwobject (string url)
{
if (Gamevar.wwwcache)
www = WWW.LoadFromCacheOrDownload (URL, gamevar.version);
Else
www = new www (URL);
}
Public IEnumerator Load ()
{
Debug.Log ("Start loading:" + Www.url);
while (!www.isdone)
{
if (gamevar.gamestate = = Gamestate.jumping | | Gamevar.gamestate ==gamestate.jumpingasync)
loadscene.progress = www.progress;
Yield return 1;
}
if (www.error!= null)
Debug.logerror ("Loading error:" + Www.url + "\ n" +www.error);
Else
Debug.Log ("End loading:" + Www.url);
}
Public IEnumerator Loadwithtip (string resourcesname)
{
Debug.Log ("Start loading:" + Www.url);
LOADSCENE.TIPSTR = "Downloading resources<" + resourcesname + "> ...";
while (!www.isdone)
{
if (gamevar.gamestate = = Gamestate.jumping | | Gamevar.gamestate ==gamestate.jumpingasync)
Loadscene.progress= www.progress;
Yield return 1;
}
if (www.error!= null)
Debug.logerror ("Loading error:" + Www.url + "\ n" +www.error);
Else
Debug.Log ("End loading:" + Www.url);
}
}
Call:
Using Unityengine;
Using System.Collections;
Using System.Collections.Generic;
public class Loadresources:monobehaviour
{
static string url = "Http://61.149.211.88/Package/test.unity3d";
public static www www = null;
IEnumerator Start ()
{
if (! gamevar.resourcesloaded)
{
Gamevar.gamestate = gamestate.jumping;
Wwwobject obj = new Wwwobject (URL);
www = obj.www;
Yield return startcoroutine (obj. Loadwithtip ("textures"));
Gamevar.resourcesloaded = true;
Gamevar.gamestate = Gamestate.run;
}
}
}
:
http://game.ceeger.com/forum/read.php?tid=13148
http://www.zhihu.com/question/23895384
http://blog.csdn.net/tkokof1/article/details/11842673
http://blog.csdn.net/tkokof1/article/details/12834939
http://www.richardfine.co.uk/2012/10/unity3d-monobehaviour-lifecycle/
http://dsqiu.iteye.com/blog/2029701