Unity3D中的线程与协程

线程 

  Unity3D是以生命周期主线程循环进行游戏开发。html

  Unity3D中的子线程没法运行Unity SDK(开发者工具包,软件包、软件框架)跟API(应用程序编程接口,函数库)。编程

  限制缘由:大多数游戏引擎都是主循环结构,游戏中逻辑更新和画面更新的时间点要求有肯定性,必须按照帧序列严格保持同步,不然就会出现游戏中的对象不一样步的现象。虽然多线程也能保证这个效果,可是引用多线程,会加大同步处理的难度与游戏的不稳定性。c#

  可是多线程也是有好处的,若是不是画面更新,也不是常规的逻辑更新(指包括AI、物理碰撞、角色控制这些),而是一些其余后台任务,好比大量耗时的数据计算、网络请求、复杂密集的I/O操做,则能够将这个独立出来作成一个工做线程,这须要写Unity游戏的Native扩展。网络

协程

  对于Unity3D,它是生命周期主线程循环的设计,它更倾向于使用Time slicing(时间分片)的Coroutine(协程)去完成异步任务,融合到生命周期中。多线程

  线程是操做系统级别的概念,现代操做系统都支持并实现线程,线程的调度对应用开发者是透明的,开发者没法预期某线程在什么时候被调度执行。基于此,通常那种随机出现的BUG,多与线程调度相关。框架

  而协程Coroutine是编译器级别的,本质是一个线程时间片去执行代码段。它经过相关的代码使得代码段可以实现分段式的执行,显式调用yield函数后才被挂起,从新开始的地方是yield挂起的位置,每一次执行协程会跑到下一个yield语句。协程能保留上一次调用时的状态(即全部局部状态的一个特定组合),每次过程重入时,就至关于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。异步

  在Unity3D中,协程是可自行中止运行 (yield),直到给定的 YieldInstruction 结束再继续运行的函数。协程 (Coroutines) 的不一样用途: ·函数

       (1) yield return null - 这一帧到此暂停,下一帧再从暂停处继续,经常使用于循环中。工具

       (2) yield return new WaitForEndOfFrame - 等到这一帧的cameras和GUI渲染结束后再今后处继续,即等到这帧的末尾再往下运行。这行以后的代码仍是在当前帧运行,是在下一帧开始前执行,跟return null很类似。oop

       (3) yield return new WaitForFixedUpdate - 在下一次执行FixedUpdate的时候继续执行这段代码,即等一次物理引擎的更新。

       (4) yield return new WaitForSeconds(3.0f) - 等待3秒,而后继续今后处开始,经常使用于作定时器。

       (5) yield return WWW - 等待直至异步下载完成。

       (6) yield return StartCoroutine(methodName) - 等待另外一个协程执行完。这是把协程串联起来的关键,经常使用于让多个协程按顺序逐个运行。

  (7)yield break - 直接跳出协程,对某些断定失败必须跳出的时候,好比加载AssetBundle的时候,WWW失败了,后边加载bundle没有必要了,这时候能够yield break跳出。

  值得注意的是 WaitForSeconds()受Time.timeScale影响,当Time.timeScale = 0f 时,yield return new WaitForSecond(x) 将不会知足。

 

  如下为Unity3D的生命周期循环图

c#代码示例

Unity3D使用协程常须要用到辅助类Stopwatch,提供一组可用于准确地测量运行时间的方法和属性。

private Stopwatch frameStopwatch;//用来记录上一帧结束到如今所用的时间
private float targetFrameDuration;//自定义的每帧持续时间,防止协程过分消耗线程时间片
private void Awake()
{
    frameStopwatch = new Stopwatch();
}

void Update()
{
    //计算每一帧所用的时间Start()以后Elapsed会一直增长,Stop()以后Elapsed的值就不变
    frameStopwatch.Stop();
    frameStopwatch.Reset();
    frameStopwatch.Start();

  if(ChunkUpdateList.Count > 0)
  {
    StartCoroutine(ProcessChunkQueueLoop());//启动协程处理ChunkUpdateList
  } }

private IEnumerator ProcessChunkQueueLoop()
{
    while (ChunkUpdateList.Count > 0)
    {
        ProcessChunkUpdateList();//每次处理ChunkUpdateList中的一个数据
        if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration)//这一帧已经运行的时间frameStopwatch.Elapsed.TotalSeconds已经超过自定义每帧的时间targetFrameDuration,则挂起直到这一帧结束再运行
        {
            yield return new WaitForEndOfFrame();
        }
    }
}

 

引用:

  (1)游戏引擎Unity中的单线程与多线程

其余:

  (1)游戏主循环

  (2)3D引擎多线程:渲染与逻辑分离

相关文章
相关标签/搜索