在项目开发过程中动画表现需要考虑到其实现的经济性与适合的应用场景。常用的动画形式有以下几种简单动画-Update实现简单动画-Tween实现Animator顶点动画骨骼动画序列帧Shader UV动画粒子特效PS粒子特效可以被视为动画表现的一种形式。但是由于其非线性的特点不在这里展开描述。见文Unity性能优化_粒子特效(Particle System)-CSDN博客一 简单动画-Update通过在Update方法中进行特定逻辑的编码。比如操作transform对象的positionlocalRotationlocalScale。特别需要指出的是因为对性能要求的敏感性核心玩法中对3D GameObject的操作应该使用最基础的实现比如玩家角色移动Monster对象的移动子弹运动等。而不要使用xxxTween降低代码自由度和可读性的同时还会带来大量的GC操作。二 简单动画-Tween常见的就是UI的动画用xxxTween比如DoTween来实现足以满足需求。三 AnimatorAnimationUnity原生组件大家最熟悉制作一些更为复杂的动画效果比Tween更直观也方便团队协作。Animator CullingMode 可见性更新Cull Update Transformations表示如果该动画不可见则不会渲染该动画但是依然会根据该动画的播放来改变游戏对象的位置、旋转、缩放是常用的选项。Animation CullingType一般设置成AlwaysAnimate慎重考虑设置成BasedOnRenderers需要更严格的实现动画状态播放逻辑。属性访问字符串转Hash值通过Animator.StringToHash来转换 Animator 属性名称避免重复的Hash计算。Animator animator GetComponentAnimator (); //正常情况播放动画的方法 animator.SetBool (animName1, true); animator.SetFloat (animName2, 1f); //优化播放的方法 int hashValue1 Animator.StringToHash (animName1); int hashValue2 Animator.StringToHash (animName2); animator.SetBool (hashValue1, true); animator.SetFloat (hashValue2, 1f);检查Animator.Rebind开销简化Animator对象尽量在Animator中减少不需要动画的物体减少动画中MonoBehaviour的字段数量.部分动画曲线和关键帧较多建议去掉冗余数据⽤⼯具压缩。压缩动画浮点数精度通过扫描*.anim文件for (int ii 0; ii clipAnims.Length; ii) { ClipAnimationInfoCurve[] newCurves clipAnims[ii].curves; //Debug.LogFormat(OnPostprocessFBX : newCurves Clip Count : {0}, newCurves.Length); if (newCurves null) { continue; } foreach (ClipAnimationInfoCurve animCurve in newCurves) { if (animCurve.curve null) { continue; } Keyframe[] keyFrames animCurve.curve.keys; for (int i 0; i keyFrames.Length; i) { Keyframe key animCurve.curve.keys[i]; key.value float.Parse (key.value.ToString (f3)); key.inTangent float.Parse (key.inTangent.ToString (f3)); key.outTangent float.Parse (key.outTangent.ToString (f3)); keyFrames[i] key; } animCurve.curve.keys keyFrames; } clipAnims[ii].curves newCurves; }去除Scale曲线foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings (theAnimation)) { string name theCurveBinding.propertyName.ToLower (); if (name.Contains (scale)) { AnimationUtility.SetEditorCurve (theAnimation, theCurveBinding, null); } }减低曲线精度……四 顶点动画五 骨骼动画更为复杂的动画形式无法进行批处理消耗更多CPU/GPU算力一般在注重角色表现的项目中使用可以实现角色全身的复杂动画。Import Settings – 没有动画的模型确保关闭RigsImport Settings – MeshSkinning.Update时间勾选Optimize Game Objects可以优化⻣骼层级减少矩阵运算。Animation 开启动画压缩如果Optimal压缩异常则回退到KeyframeReduction可见性更新禁用 Update When Offscreen 可以减少 CPU 和 GPU 的负担但可能是一个负优化策略。为了保持动画的流畅和一致性需要保持该选项启用。Skinned GPU Skinning把骨骼矩阵存烘焙在配置文件里面然后通过特殊的shaderCompute Shader计算顶点的位置直接在GPU端得到了网格模型的顶点在动画帧该在的位置。 这一切由于是在GPU端直接得出结果所以根本不会产生CPU的合并和DrawCall。还能通过引入GPU Instancing技术进一步优化。《戴森球》就是这种做法看到有人为此开发了专门的插件。骨骼LOD程序化的实现情况下动作看起来可能不自然一些细节骨骼丢失所以如果美术DCC多蒙几套可能视觉还会好点。程序化的肯定是严格按某些骨骼节点结构来做看上去应该没有美术调的过度自然。Unity默认不支持程序化Lod需要改到源码。当然此方案需要消耗更多的内存。JobSystem化GitHub - Unity-Technologies/animation-jobs-samples: Code samples using the animation C# jobs feature. · GitHub六 序列帧预录制的动画因为是用贴图的形式来存储不同时间点的变化信息需要消耗更多的内存空间。可以通过减少单位时间内的播放帧数来降低内存的占用但是需要考虑到动画品质的要求做权衡。一般对于一些不重要的屏占比低动作不复杂3D角色可以使用少量的序列帧来处理。而由于像素尺寸小所以可以把多个角色的不同动作状态都录制在一张贴图上通过Gpu Instancing的形式进行批处理。PS三转二(3D转2D)通过建模- 绑骨骼-k动作-导出序列帧。一些适合采用序列帧的案例有使用粒子特效来实现不同颜色的蝴蝶蜜蜂等微小动物。使用骨骼动画来制作小兵动作而小兵角色一般都有大量出现的场景。七 Shader UV 动画上面提到的序列帧通过GPU Instancing的实现方式其实就是一种利用Shader UV动画原理的案例。