参考:
Unity3d 10000 Update() calls 性能优化
总结
微协程是内存高效、快速的协程 worker,是基于 Unity3d 10000 Update() calls 这篇文章阐述的思想实现的
使用 MicroCoroutine 来替换一般的 Coroutine:
1 | int counter; |
MicroCoroutine 的局限性
只支持
yield return null更新时机由启动方法(
StartUpdateMicroCoroutine()、StartFixedUpdateMicroCoroutine()、StartEndOfFrameMicroCoroutine())决定
进阶
Unity3d 10000 Update() calls 这篇文章主要阐述的思想(建议直接看原文或译文):
开展讨论的例子
MonoBehaviour 中可以定义一些特定的魔术方法,如:Update() 等,这些方法通常有以下问题:
- 不清楚方法是如何被调用的
- 不清楚多个
MonoBehaviour之间,这些方法的调用顺序 - 非
IDE友好
有开发者通过扩展 MonoBehaviour 抽象出一个新的统一的 BaseMonoBehaviour,来减少上述的不足:
1 | public abstract class BaseMonoBehaviour : MonoBehaviour { |
但这种做法会带来新的问题:所有继承 BaseMonoBehaviour 的脚本,上述声明的魔术方法都会在特定时机被执行,比如在每帧执行 Update() 方法,即使它是一个空方法
性能分析调用 10000 个像 Update() 这样的方法
具体测试流程略可看原文(PS:原文列出的代码比较难理顺逻辑,推荐结合完整的项目代码分析)
原文主要做了 3 种操作的耗时对比:
Unity内部迭代 10000 个MonoBehaviour的Update()方法列表类型循环迭代 10000 个
ManagedUpdateBehavior的UpdateMe()方法数组类型循环迭代 10000 个
ManagedUpdateBehavior的UpdateMe()方法
总结
Unity在调用像Update()这样的魔法方法时,为了防止游戏出错或崩溃,通常都需要做很多的检测和处理,因此当有大量的MonoBehaviour时,这些处理累计的耗时就不能轻易忽视了删除不必要的魔术方法是很有意义的,而上述抽象出
BaseMonoBehaviour这种做法是不可取的在开发过程中,当考虑到有大量的对象需要在每帧都执行一些操作时,可以参考使用如原文测试例子的
Manager模式,采用数组结构循环迭代调用对象的更新操作,减少耗时MicroCoroutine就是基于此思想,对一般的Coroutine函数以数组结构进行组织,来实现内存高效、快速的协程调用,但同时也有一定的限制(见上文)