UPL5-3——Update 相关
UPL5-3——Update 相关
移除空 Update
如果在脚本中定义了生命周期函数,但没有在其中写任何逻辑,他们仍然会带来额外的性能开销
因此我们要避免在脚本中写空的生命周期函数
特别是那些会每帧调用的生命周期函数
-
Update -
LateUpdate -
FixedUpdate -
OnGUI
需要在 Update 中频繁使用的组件应该缓存
在 Unity 中反复获取一个组件是一种常见错误,对于一些常用的组件,我们不应该每次都重复的去获取,
应当通过泛型获取组件的方式将其缓存下来
我们应该避免在 Update 中调用如:
-
GetComponent寻找组件相关API -
Find寻找对象相关API
等等
降低执行频率
我们时长会在 Update 中重复执行一些逻辑,如果超出需要的频率重复调用某些代码,会造成性能的浪费
比如:怪物 AI 中,怪物需要不停的朝玩家寻路并移动,如果我们在 Update 中不停每帧重复寻路会造成不必要的性能浪费
我们可以通过降低执行频率来避免性能浪费,最常用的方式就是自定义更新间隔
1 | private float _updateTime = 0.25f; // 间隔多久更新一次 |
减少复杂计算
我们要尽量减少在 Update 中进行复杂的数学计算,对于一些不变的计算结果
应该在初始化时(Awake、Start 中)就计算好 Update 中直接使用
事件驱动代替每帧检测
利用观察者模式取代在 Update 中每帧进行状态检测,例如:将 玩家每帧检测怪物血量判断怪物死亡 改为 怪物死亡时通知玩家怪物死亡
观察者模式的一个实践就是 事件中心,相关实现可参考:UFL4——事件中心模块
分帧执行
对大批量对象更新时,使用异步方法,或者自行记录的方式进行分帧处理,避免单帧卡顿
Unity 的协同程序也可以达到对应效果,但是协程自身存在也有一些性能问题需要解决,详见:UPL5-4——协程相关
1 | private int _index; |
自定义 Update 管理器(统一管理 Update 更新)
在 Unity 中,如果每个继承 MonoBehaviour 的脚本独立处理 Update 生命周期函数
当这样的对象过多时,由于引擎底层机制(Unity 底层 C++ 层调用 C# 会有跨语言的开销、内存连续访问问题),会增加性能的开销
如果我们对 Update 进行统一管理,可以大幅提升性能,并且独立调用 Update 生命周期函数的对象越多,统一管理器的优势就越明显(特别是中大型对象场景中对象非常多时)
优化方式:
通过一个统一更新管理器 统一 对所有需要 Update 更新的脚本进行管理,只需要一个 Update 生命周期函数 执行所有对象的更新
对应的实现可参考公共 MonoBehaviour 管理器,相关内容:UFL2——公共Mono模块
公共 MonoBehaviour 管理器中是通过 事件 记录所有Update函数的,也可以通过列表记录对象的形式调用
