A brief analysis of "Unity3d" the cut of the continuous and disorderly yield

Source: Internet
Author: User

It's easy to see the following example when learning Unity3d:

1 void Start () {2     startcoroutine (Destroy ()); 3}4 5 IEnumerator Destroy () {6     yield return waitforseconds (3.0f); 7< C3/>destroy (Gameobject); 8}

This function is simple: Call the Startcoroutine function to open the process, yield wait for a period of time after the destruction of the object, because the process is waiting, so does not affect the main thread operation. Generally, the time to see here is not faint, yield is delayed after a period of time to continue to execute Bai, en, learned, and looked very useful.

==================================================== Split Line ====================================================

Of course, yield can do much more than this simple specific time delay, for example, the next frame can continue to execute the code (yield return null), the next time the execution of Fixedupdate will continue to execute this code (yield new Waitforfixedupdate ();), you can let an asynchronous operation (such as Loadlevelasync) continue after completion, you can ... Can make you see dizziness.

Unity3d official interpretation of the process is that a synergistic program can use the yield statement anywhere during execution. The return value of yield controls when the recovery of the synergistic program executes downward. The Synergy program is excellent during the execution of the object's own frame. The synergistic program has no more overhead in performance. The Startcoroutine function is returned immediately, but yield can delay the result. Until the execution of the collaboration program is complete. (Original: The execution of a coroutine can be paused on any point using the yield statement. The yield return value specifies when the coroutine is resumed. Coroutines is excellent when modelling behaviour over several frames. Coroutines has virtually no performance overhead. Startcoroutine function always returns immediately, however you can yield the result. This'll wait until the coroutine has finished execution.)

If you just think yield for delay, then it can be used very smoothly, but if you see yield and so many functions, visual instantaneous messy, not to mention ingenious. However, if the principle of understanding, it is easy to clarify the various functions of yield.

Yield in C #

1 public static ienumerable<int> Generatefibonacci () 2 {3     yield return 0; 4     yield return 1; 5  6     int last0 = 0, Last1 = 1, current; 7  8 while     (true) 9     {Ten current         = last0 + last1;11         yield return current;12         last0 = last1;14
   last1 = current;15     }16}

The effect of yield return is to return control immediately to the outside after executing this line of code. The code after yield return executes when the external code calls MoveNext again, until the next yield return--or iteration ends. Although the above code seems to have a dead loop, in fact inside the loop we always return control to the outside, which is the outside to decide when to abort this iteration. With yield, we can use the "dead loop", and we can write the "infinite" Fibonacci sequence with a definite meaning. Turn from Lao Zhao's blog.

The difference between IEnumerable and IEnumerator is small, only IEnumerator in Unity3d, function and IEnumerable are similar. As for their differences, online search for a long day, or vague, there are children's shoes can explain clearly please leave a message. However, this code is sufficient for the understanding of yield in unity3d.

A scenario in which you need to use yield in the game

If you want to use yield, you have to give it a reason not to use yield in order to use yield. So let's take a look at the scenario where the game can be used to yield:

    • When the game settles scores, the score rises from 0 instead of displaying the final score directly

    • When people talk, the text appears one at a time rather than suddenly
    • 10, 9, 8 ... Countdown to 0

    • Some games (such as the King of the Fist) lose blood when the UI of the blood bar gradually decreases, rather than suddenly lowering to the current amount of blood

..............................

Example of yield application in Unity3d

The first is a section of the official website code:

1 using Unityengine; 2 using System.Collections;  3  4 public class Yield1:monobehaviour {5  6     IEnumerator does () {7         print ("Do Now"); 8         yield return new Waitforseconds (2); 9         Print ("Do 2 seconds later"),     }11     void Awake () {         startcoroutine (do ());         Printed immediately "),}15/Use the for     initialization17     void Start () {     }20     //update is called once per frame22     void Update () {     }25}

This example will do, but the print command after the DO function executes immediately. This example has no practical significance, just to verify that yield does have a delay.

Here's a look at two pieces of code that shows a character's conversation (a conversation randomly duplicates a piece of content), and the function is the same, but the method is different:

 1 using Unityengine; 2 using System.Collections; 3 4 public class Dialog_easy:monobehaviour {5 public string DIALOGSTR = "yield return" is the function of returning control immediately to the outside after executing this line of code. The code after yield return executes when the external code calls MoveNext again, until the next yield return--or iteration ends. Although the above code seems to have a dead loop, in fact inside the loop we always return control to the outside, which is the outside to decide when to abort this iteration. With yield, we can use the "dead loop", and we can write the "infinite" Fibonacci sequence with a definite meaning. "; 6 Public float speed = 5.0f; 7 8 Private float timesum = 0.0f;      9 private bool isshowing = FALSE;10//Use this for initialization11 void Start () {ShowDialog (); 13 }14//update is called once per Frame16 void Update () {+ if (isshowing) {             Um + = speed * time.deltatime;19 guitext.text = dialogstr.substring (0, System.Convert.ToInt32 (timesum)); 20 21 if (guiText.text.Length = = dialogstr.length) isshowing = false;23}24}25 OID ShowDialog () {isshowing = true;28 timesum = 0.0f;29}30} 

This code implements the ability to gradually display a string in Guitext, at a speed of 5 words per second, which is a common way for beginners. If you simply display a piece of text in Guitext, the ShowDialog () function can do well, but if you want the word to pop out, you need to use the loop of the game, and the simplest way is to update the Guitext in Update ().

  from a functional point of view, this code is completely fine, but from a code encapsulation standpoint, this is a nasty piece of code , because the functionality that should have been done by ShowDialog () is placed in update (). And there are two private variables in the class that serve this function. If you want to modify or delete this feature in the future, you need to modify it in ShowDialog () and update (), and you may also modify the two private variables. Now the code is relatively simple, the feeling is not too bad, once the update () in another two class-like function, estimated to write the code after a period of time to modify their own laborious.

If you use yield return NULL to achieve synchronization between frames and frames, the code is a lot more elegant:

1 using Unityengine; 2 using System.Collections; 3  4 public class Dialog_yield:monobehaviour {5 public     string dialogstr = "yield return has the effect of returning control immediately after execution to this line of code Department. The code after yield return executes when the external code calls MoveNext again, until the next yield return--or iteration ends. Although the above code seems to have a dead loop, in fact inside the loop we always return control to the outside, which is the outside to decide when to abort this iteration. With yield, we can use the "dead loop", and we can write the "infinite" Fibonacci sequence with a definite meaning. "; 6 public     Float speed = 5.0f, 7  8/Use the for     initialization 9     void Start () {Ten         startcoroutine (Sho Wdialog ());     }12     //update is called once per frame14     void Update () {     }16     IEnumerator ShowDialog () {         float timesum = 0.0f;19 while         (GuiText.text.Length < dialogstr.length) {20             Timesum + = speed * time.deltatime;21             guitext.text = dialogstr.substring (0, System.Convert.ToInt32 (timesum) );             yield return null;23         }24     }25}

The relevant code is encapsulated in ShowDialog (), which makes it much easier to add, modify, or delete features.

According to the official website manual, yield return null allows this code to continue execution at the next frame. In ShowDialog (), yield return null each time the text is updated until the text is fully displayed. See here, there may be children's shoes puzzled:

    • Why is it possible to use Time.deltatime in a co-process?
    • Does the time.deltatime in the process be the same as in update ()?
    • Does this use a thread that conflicts with the main thread access shared resource? (Synchronization and mutex issues for threads)
    • Yield return null is amazing, why does this function continue in the next frame?
    • Is this code equivalent to constructing a own update () for ShowDialog ()?

To explain these problems, first look at how the Unity3d in the process is running.

Analysis of the principle of co-process

This paragraph of the content is transferred from this blog, want to see the children's shoes click on their own.

First, keep in mind that the process is not a thread, nor is it executed asynchronously. The Monobehaviour and the update function are also executed in Mainthread. Using the coprocessor you don't have to worry about syncing and locking issues.

Unitygems.com gives the definition of the co-process:

  A coroutine is a function this is executed partially and presuming suitable conditions was met, would be resumed at some p Oint in the "future until" it is done.

The co-process is a partial execution, and the condition (yield return statement) hangs until the condition is met before it wakes up to execute the subsequent code. Unity handles the threads on the object at each frame. Unity mainly handles the process after the update (checking that the conditions of the Association are satisfied):

From the analysis, it is understood that the co-process is the same as update (), which is the function (if any) that the unity will handle for each frame. If the monobehaviour is in the active state and the yield condition is met, the code behind the method will be followed. It can also be found that if you call the co-process at the beginning of an object, the co-process will immediately run to the first yield return statement, and if yield return null, it will be awakened again at the same frame. There are some strange problems if you don't consider this detail.
Note: Both the graph and the conclusion are obtained from the unitygems.com, after the verification found and the actual discrepancy , D.s.qiu uses the unity 4.3.4F1 to carry on the test. After testing, the co-process is at least lateupdate () after each frame to run .

The process is actually a IEnumerator (iterator), the IEnumerator interface has two methods of current and MoveNext (), the iterator method runs to the yield return statement, Returns an expression and retains the current position in the code. The next time the iterator function is called, execution restarts from that location. What Unity3d does at each frame is to invoke the MoveNext (iterator) method and, if true, to proceed from the current position. See this blog for details.

If you understand this diagram, the last few questions that show the function of the character's conversation are easy to understand:

    • The Time.deltatime is updated as well as update (), and the time.deltatime is used in the same way as in Update () (with yield return null)
    • The process is not multi-threaded, it is executed in the main thread like update (), so there is no need to deal with thread synchronization and mutex issues
    • Yield return Null In fact nothing magical, just unity3d encapsulation, the process is automatically called in the next frame
    • It can be understood that showdialog () constructs a own update (), because yield return null allows the function to be called every frame.

A brief analysis of "Unity3d" the cut of the continuous and disorderly yield

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.