关于Unity动画系统优化,你可能遇到这些问题

关于Unity动画系统优化,你可能遇到这些问题

关键字

内存泄漏
资源制作


一、内存泄漏

Q1:我们测试发现,当Animator Controller挂载的动作比较多时,即使切换成另外一个动作很少的Animator Controller,任务的动作信息还是不会释放。我们将英雄打成一个AssetBundle,然后又把定制的Runtime Animator Controller加载替换进去,英雄自带的Runtime Animator Controller是挂了所有动作的。我们试了替换Runtime Animator Controller之后,把先前的Runtime Animator Controller Destroy掉,貌似内存也没释放。
请输入图片描述

销毁Animator Controller并不会释放其内所引用的AnimationClip资源的,所以内存没有明显下降是正常的。建议按照以下方式做个试验:
1)销毁Animator Controller 后,通过Unity Profiler立刻真机Take Sample,查看Animation Clip的Ref count是否为0;
2)如果不是,则需要进一步查看这些资源的索引出处;如果为0,则可以通过UnloadUnusedAssets或UnloadAsset来将其从内存> 中去除。


二、资源制作

Q1:Optimize Game Objects对于老版本的Animation系统有没有作用呢?

没有作用。Optimize Game Objects功能是Unity4.3版本推出的功能,且仅对Mecanim动画系统起作用。如果可以的话,建议研发团队尽可能使用Mecanim来作为项目动画系统的解决方案。

Q2:在UWA性能报告中,你们建议我们选中Optimize GameObject来提升Mecanim动画模块的运行性能,但是这个功能会隐蔽角色骨骼,那么要挂载该骨骼上的这个点就无法查询了,有什么办法可以解决这个问题吗?

是的,开启Optimize GameObject默认情况下会将动画网格下的所有骨骼结点隐藏,但是,你可以通过“Extra Transform to Expose”查看你想通过脚本获取的骨骼结点,这样既可以提升该角色的动画模块性能,又可以达到获取某个关键结点的需求。
请输入图片描述

Q3:SkinnedMeshRenderer.BakeMesh这个函数一般是什么时候调用呢?在Instantiate后调用么?

SkinnedMeshRenderer.BakeMesh 的作用在于:将一个蒙皮动画的某个时间点上的动作,Bake成一个不带蒙皮的Mesh,从而可以通过自定义的采样间隔,将一段动画转成一组Mesh序列帧。而后在播放动画时只需选择最近的采样点(即一个Mesh)进行赋值即可,从而省去了骨骼更新与蒙皮计算的时间。
该方法的优点是用内存换计算时间,在场景中大量出现同一个带动画的模型时,效果会非常明显。该方法的缺点是内存的占用极大地受到模型顶点数、动画总时长及采样间隔的限制。因此,该方法只适用于顶点数较少,且动画总时长较短的模型。同时,Bake的时间较长,因此需要在加载场景时完成。
比较经典的适用场景为MOBA游戏中的小兵。

Q4:在UWA给出的报告中,我们发现了Animator过高的情况,其中UI和角色各占一半。我们之前一直选择CullUpdateTransforms,通过阅读Unity官方文档发现CullCompletely更符合我们的现状,想请教下如果我们选择CullCompletely可能会有什么隐患呢?

使用 CullCompletely 在开启 RootMotion 时是需要注意的,比如人物有一个巡逻动画是通过 RootMotion 制作的,那么在人物走出屏幕后,其动画就停止了,即不会再走回屏幕中。

Q5:我们在美术制作时做了40根骨骼,但在动作中仅用到了其中的30根。这种做法和30根骨骼用到了30根相比,在蒙皮计算上会明显增加吗?(Animation经过了压缩处理)

理论上是有增加的,骨骼运算均是每个骨骼阶段的Matrix乘起来的,所以理论上会有开销。建议使用Optimize GameObejct选项,可以减少一些不必要的CPU开销。