Unity3D中的线程与协程 |
您所在的位置:网站首页 › unity关闭线程 › Unity3D中的线程与协程 |
线程
Unity3D是以生命周期主线程循环进行游戏开发。 Unity3D中的子线程无法运行Unity SDK(开发者工具包,软件包、软件框架)跟API(应用程序编程接口,函数库)。 限制原因:大多数游戏引擎都是主循环结构,游戏中逻辑更新和画面更新的时间点要求有确定性,必须按照帧序列严格保持同步,否则就会出现游戏中的对象不同步的现象。虽然多线程也能保证这个效果,但是引用多线程,会加大同步处理的难度与游戏的不稳定性。 但是多线程也是有好处的,如果不是画面更新,也不是常规的逻辑更新(指包括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很相似。 (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) { ProcessChunkQueueLoop();//处理ChunkUpdateList } } private void ProcessChunkQueueLoop(){ while (ChunkUpdateList.Count > 0) { ProcessChunkUpdateList();//每次处理ChunkUpdateList中的一个数据 if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration)//这一帧已经运行的时间frameStopwatch.Elapsed.TotalSeconds已经超过自定义每帧的时间targetFrameDuration,则挂起直到这一帧结束再 break; }}
引用: (1)游戏引擎Unity中的单线程与多线程 其他: (1)游戏主循环 (2)3D引擎多线程:渲染与逻辑分离
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |