动画优化
前言
本文专门记录最近对动画优化的一些研究和思考
参考文献
FastPath
这个比较简单, 就是在动画图表中不要加入蓝图逻辑, 保证了只在引擎能够在内部复制参数,而不是执行蓝图代码(这涉及调用蓝图虚拟机)
如果是FastPath, 动画节点上会有个闪电的标志
模型刷新 Visibility Based Anim Tick Option
在角色蓝图中,可以对Mesh组件设置Visibility Based Anim Tick Option,可选的选项分别是:
- AlwaysTickPoseAndRefreshBones:无论是否渲染,总是tick和Refresh Bone transforms。
- AlwaysTickPose:总是tick,只在渲染时Refresh Bone transforms。
- OnlyTickMontagesWhenNotRendered:只在渲染时tick pose和Refresh Bone transforms。 不渲染时,只更新montage,跳过其他操作。
- OnlyTickPoseWhenRendered:只在渲染时tick和Refresh Bone transforms。
需要注意的是, 在渲染的时候是一定都会TickPose和Refresh Bone transforms的, 枚举的命名可能有一些歧义
结合之前的文章动画逻辑深入分析, 可以判断, TickPose就是跑动画蓝图的Tick流程和状态机, Refresh Bone transforms 就是刷新骨骼,
为了验证上面的猜测我们做一下测试
我们让角色走路动画加一个通知, 如下
然后通知播放一个2D音效和打印当前时间
第一个情况是AlwaysTickPoseAndRefreshBones
可以看到即使背对角色 角色还是正常播放动画, 也可以看到通知的正常运行
然后是AlwaysTickPose
动画蓝图还在跑, 但是角色已经没有动作了
接下来是OnlyTickMontagesWhenNotRendered
我们让角色移动一次结束以后播放一个蒙太奇动画, 顺便在蒙太奇动画里加上一串通知
看效果
结果就是蒙太奇逻辑还在跑, 但是骨骼照样没有刷新
最后是OnlyTickPoseWhenRendered
这个就是不渲染的时候啥也不干了
URO
URO即Update Rate Optimization, 即刷新帧率优化
开启方式如下图, 在模型组件的优化标签下
开启以后如果不通过控制台设置强制的刷新频率 或者设置为0 如下图, 那么就使用引擎自己计算的刷新帧率
自己的刷新帧率怎么计算的? 看了一些代码大致如下
在SkinnedMeshComponent::TickUpdateRate()
开始
首先判断是否开启了URO, 然后刷新URO需要用到的一个数据结构 FAnimUpdateRateParametersTracker
一路F12看下去看到几个关键点
如果没有被渲染 , 那么走上面图片的帧率
否则就走到下面这里
期望的帧率DesiredEvaluationRate
会跟BaseVisibleDistanceFactorThesholds
的2个成员进行比对, 而MaxDistanceFactor
的值来自下图
这个值最终来自UpdateLODStatus_Internal()
函数, 跟LOD有关系, 我们可以用控制台a.VisualizeLODs 1
看到模型的LOD信息, 如下图
所以如果按照小白人的情况, 根据距离DesiredEvaluationRate
一般在1-3的值切换
同样的, 我们可以用控制台命令强行设置刷新率
比如a.URO.ForceAnimRate 10
, 看到下面效果, 妥妥的幻灯片
但是还有一个选项, 用控制台输入a.URO.ForceInterpolation 1
开启插值计算, 效果如下
效果已经得到很大的改善, 但是开销会增加, 不过模型中有一些优化选项可以视情况勾选
另外还有一个有趣的选项, RenderStatic
如果勾选, 那么场景中的角色就不再渲染动画, 但是动画蓝图中实际上还是可以看到骨骼还是在刷新的