Tick:你真的需要每帧执行吗
如果只学一个性能习惯,学这个:Tick 是昂贵的,少用。
每个 Tick 的 Actor/组件都要在场景的 Tick 列表里占一格;蓝图 Tick 还要穿越 VM 边界。场景里有 1000 个开着 Tick 的 Actor,每帧就是 1000 次调度——即使每个 Tick 函数体是空的。
三个问题自检
- 它必须每帧更新吗? 很多逻辑其实只在事件发生时才需要跑(受击、移动结束、状态切换)。改成事件驱动。
- 它必须对所有对象都 Tick 吗? 远处的敌人、屏幕外的 UI 动画,可以按重要性分级。
- 它的频率可以降低吗? 用 Timer(
SetTimer,如 0.1s 一次)代替 Tick,多数"轮询类"逻辑足够了。
具体替代手段
| Tick 的用途 | 替代 |
|---|---|
| 定期检查状态 | SetTimer 轮询(0.1~0.5s) |
| 等待条件成立 | 事件/委托(条件变化时广播) |
| 移动 | FloatingPawnMovement / ProjectileMovement(内置插值与网络同步) |
| UI 定时刷新 | 事件驱动 + 动画曲线 |
| 必须每帧但看距离 | 按距离分级(近处 Tick、远处关) |
蓝图 Tick 的两个隐藏成本
- 事件图表本身的开销:Tick 节点即使没连线也存在;连了几十个节点的 Tick 图表,每帧穿越 VM。
Tick里的Get/Cast/FindComponent:每帧重复查找,参见上页的"缓存"方案。
一个真实案例
80 个小怪的"回血逻辑"原本写在蓝图 Tick(每帧检查血量、判断是否脱战、加血)。改为:受击/脱战由事件驱动,回血用 0.5s Timer。CPU 从 ~9ms/帧降到 ~2ms/帧,而行为表现一模一样。
项目级自查
- 蓝图里
Event Tick用了多少?可以开stat Blueprint(或者用 Insights)看蓝图 VM 开销分布。 - 用 Unreal Insights 的 Frames 视图定位:哪个对象的 Tick 在热点里。
相关官方资料:Gameplay 定时器
本章小结
- Tick 是项目变卡的第一大来源:能停的 Tick 停,能降频的降频,能事件化的事件化。
- 替代手段:
SetTimer轮询、事件/委托驱动、MovementComponent、距离分级。 - 蓝图 Tick 额外成本:VM 穿越 + 图表内重复查找(缓存解决)。
