Detailed description of Coroutine in Unity3D, unity3dcoroutine
Coroutine in Unity is implemented through yield expression. Such code is everywhere in the official script.
Question:
What is yield?
What is Coroutine?
How strange is the coroutine Program Execution Process of unity?
What is the coroutine principle in unity and how is it implemented?
What should I pay attention to when using unity coroutine?
I. Program Execution features of yield in several languages:
In Lua, yield enables the collaborative function to run-> suspend and PASS Parameters to resume. Resume suspends the collaborative function-> runs and Passes parameters to the collaborative function.
In C #, yield return/break is used to query the values in the Set generator (similar to iterations) returned by the function, and record the current field. During the next query, the previous recorded yield field is located, continue to execute until the execution goes down. Then exit the yield logic. Yield break terminates the yield iteration logic and jumps out.
YieldImplementation:
1). Caller callsfunction
2). Caller requestsitem requests an element as needed
3). Next itemreturned returns the requested Element
4). Goto step #2
In the yield expression in Python, a yield function becomes a generator and the iterator object is returned when this function is called, the next method is called with the iterator object (or the next method is automatically called in the loop) to start executing the function. If the next method is executed at the yield expression, the operation is interrupted and the current value of the iterator is returned, and keep the site. The next call to next will start from the site and the iteration will stop. It can be seen that yield in Python is similar to yield in C #. It is used to create a generator, return the iterator value when the generator is interrupted during execution, record the field, and continue the execution from the field next time.
Yield in Unity is similar to C # And python, because unity is based on the. net Framework and the unity script is written in Boo (a Python variant. Only the coroutine feature type is added to unity, and the coroutine management class of StartCoroutine is added. StartCoroutine doesn't start a new thread, but starts a cool, by default, all the code of unity is in one thread (http://answers.unity3d.com/questions/280597/new-thread-vs-startcoroutine.html ).
Ii. Coroutine execution of Unity:
Method 1:
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 execution sequence of the code segment is 12435.
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 execution sequence of the code segment is 12453.
Why? This strange execution method.
III,Explanation of coroutine in the official Unity documentation:
Normal coroutine updates are run after theUpdate function returns. Aco routine is a function that can suspend its execution (yield) until the givenYieldInstruction finishes. Different uses of Coroutines:
Yield; The coroutine will continue after all Update functionshave been calledon the next frame.
Yield WaitForSeconds (2); Continueafter a specified time delay, after all Update functions have been 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 will wait for the MyFunc coroutine to completefirst.
C # Add the return keyword between yield coroutine.
Iv. Theory of Coroutine in Unity:
The Virtual Machine segment execution mechanism. The same type of nesting is stored in stacks for serial execution.: The. NET Virtual Machine enters the predefined entry for each compiler in sequence in each frame loop. For the Coroutine type, the compiler needs to generate some code after the time or event specified by the Coroutine type is completed (. net virtual machines use function pointers to mark the management site and send messages after each frame check time or event in the process is satisfied, and assign the cpu ownership to the yield interrupted site, alternatively, you can manage Coroutine by multiple management classes that contain different coroutine iterators. Each frame uses the coroutine subclass to check the time or event arrival through polymorphism and hand over the cpu ownership to the field where the coroutine subclass is interrupted ), continue to execute the code after yield is interrupted, which forms a mechanism that we can see that the function can be executed in segments.
For the nested Coroutine Type, serial execution rather than parallel execution may be performed.. net virtual machine uses the stack for storage of the same coroutine type. The top of the stack is executed first to implement serial execution. If the outer layer does not use yield return, serial execution is not performed, but parallel execution is performed. Then we can explain the execution order in the above example.
Schematic:
See: http://www.richardfine.co.uk/2012/10/unity3d-monobehaviour-lifecycle/
5. Notes for using Coroutine in Unity:
1. Use and unavailable:
Yield coroutine must be called in MonoBehaviour or a class that inherits from MonoBehaviour. Yield cannot be used in Update or FixedUpdate.
2. Enable coroutine:
StartCoroutine (string methodName) and StartCoroutine (IEnumeratorroutine) both enable a coroutine,
Differences:
When you use a string as a parameter, you can only pass one parameter at most when you enable the coroutine, and the performance consumption is greater. IEnumerator does not have this limit.
3. Delete the coroutine:
1) In Unity3D, StopCoroutine (stringmethodName) is used to terminate a coordinator of the specified Method Name of the MonoBehaviour, and StopAllCoroutines () is used to terminate all coordinator that can be terminated by the MonoBehaviour.
Including StartCoroutine (IEnumerator routine.
2) There is also a way to terminate the collaboration program, that is, to set the active attribute of the gameobject where the collaboration program is located to false. When the active attribute is set to true again, the collaboration program will not be enabled again;
If the enabled of the script in which the coprocessor is located is set to false, it does not take effect.
4. Differences between js and C:
Use yield return instead of yield in C.
In C #, the yield (Interrupt) statement must be in the IEnumerator type. The return type of the C # method is IEnumerator. The returned value is (eg: yield return new WaitForSeconds (2 ); or yield returnnull );
5. The design mode of the combination of return values and parameter types of coroutine functions:
The coprocessor returns the Coroutine type. In Unity3D, The Coroutine class inherits from YieldInstruction. Therefore, the coprocessor can only return null, the number of waiting frames (frame), and the waiting time.
The ref and out parameters cannot be specified for the coprocessor. However, we often use the collaborative program when using the WWW class, because the parameter address (reference) cannot be passed or the output object cannot be in the collaborative program,
This means that each download of a WWW object has to rewrite a collaborative program. The solution to this problem is to create a WWW-based class (which can be solved in combination mode) 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;
}
}
}
References:
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/