zoukankan      html  css  js  c++  java
  • Unity 协程深入解析与原理

    先来直接放一段代码

     1 using System.Collections;
     2 using System.Collections.Generic;
     3 using UnityEngine;
     4 
     5 public class CoroutineTest : MonoBehaviour
     6 {
     7 
     8     void Start()
     9     {
    10         Debug.Log("Start Begin");
    11 
    12         CustomCoroutine = DelayPrint("Hi");
    13 
    14         Debug.Log("Start End");
    15     }
    16 
    17     bool isStartCoroutine = true;
    18     IEnumerator CustomCoroutine = null;
    19     void Update()
    20     {
    21         Debug.Log(""+Time.frameCount+"Update 在执行");
    22         if (isStartCoroutine)
    23         {
    24             if (CustomCoroutine.MoveNext())
    25             {
    26                 Debug.Log(CustomCoroutine.Current.ToString());
    27             }
    28         }
    29         Debug.Log("" + Time.frameCount + "Update执行结束");
    30     }
    31 
    32     public IEnumerator DelayPrint(string somevalue)
    33     {
    34         Debug.Log("DelayPrint Start");
    35         yield return 0;
    36         Debug.Log("DelayPrint Debug:" + somevalue);
    37         Debug.Log("DelayPrint End");
    38     }
    39 
    40 }
    CoroutineTest

    代码结果如下:

    这样一看是不是跟我们平时在Unity使用的StartCoroutine基本上是一样的了?其实还是有不一样的地方,这因为在Unity内部对自己的协程管理作了特殊处理(猜测)。

    在Unity内的协程位置顺序图如下:

    而我们在上面写的自己的协程只会在Update里运行,因为我们在Update里写MoveNext(),若是想在其他地方运行我们的协程就写在其他地方就好~

    所以说Unity协程的本质就是Unity内部的轮询机制和IEnumerator迭代保存上下文执行代码段。

    而我们平时在协程方法yield return XXX只是把这时刻代码运行的控制权交回给主线程(类似操作系统中的挂起),其他协程或者其他线程(类似WWW类,这会真正开启另一个线程去执行,否则本质上都是单线程),,然后保存当前方法代码段的状态,等Unity内部的再次轮询回到被挂起时的代码状态继续执行,直到没有yield return的时候,这样就形成了一种代码分段执行的效果。

    也当只有yield return XXX时IEnumerator.MoveNext()才会为true,然后IEnumerator.Current是yield return XXX的XXX。

    所以在Unity里面的yield return WaitForSeconds返回给Unity中内部的协程状态机作判断处理,例如如果是返回WaitForSeconds类则给这个协程求时间差以达到延迟处理。

    如果没有yield return,也就是没有返回值,这时IEnumerator.MoveNext()为false,这就会退出了Unity轮询。

    大概就这样,要是更想理解细节的话可以百度IEnumerator和作用和把上面的代码逐步调试下即可。

    参考:https://www.zhihu.com/question/34878524/answer/61555725

       https://www.zhihu.com/question/23895384/answer/26066323

         http://dsqiu.iteye.com/blog/2029701

         CoroutineManager插件源码(这个插件是在自己的Update方法里不断轮询CoroutineManager的协程集合内,获取每个协程的MoveNext()状态,从而进行一些简单的判断管理一个协程)

  • 相关阅读:
    在js中如何将字符串类型的日期("2020-11-30T02:21:42.000+0000")进行格式化
    微信小程序:报错fail webview count limit exceed
    微信小程序:picker组件实现下拉框效果
    微信小程序:post请求参数放在请求体中还是拼接到URL中需要看后台是如何接收的
    【华为云技术分享】如何用交互式特征工程工具进行数据分析处理
    【云小课】基础服务第25课 容灾演练:平时多练兵,急时保可用!
    【华为云分享】软件工程的迷途与沉思
    WebSocket 从入门到写出开源库
    教你轻松截获 Selenium 中的 Ajax 数据
    【华为云技术分享】Scrum Master如何引导团队中的刺头
  • 原文地址:https://www.cnblogs.com/SeaSwallow/p/6561053.html
Copyright © 2011-2022 走看看