- Mesh Compression:压缩比越高模型文件越小,需要根据游戏内的实际效果决定,一般可以设置为Medium。(网格压缩,亲测质量差距比较大,不太建议开启)
- Read/Write Enable:如果你不需要运行时修改模型的话,禁用,否则启用后模型的内存消耗会增加一倍。 在不导入骨骼的情况下,开启Read/Write Enabled是不开启占用内存的两倍,不开启Read/Write Enabled占用内存和Inspector相同。在导入骨骼的情况下开不开启Read/Write Enabled都是Inspector界面显示内存的两倍 注意,ParticalSystem -> Renderer -> RenderMode如果为Mesh,则使用到的Mesh需要打开这个选项。否则会有情况从AssetBundle加载后在某些安卓设备上崩溃。
- GenerateColliders若开启,模型导入会自动建议碰撞体,静态物体根据需求开启。
- Generate Lightmap UVs:在第二UV通道存储lightmap信息。需要烘焙光照图的模型需要勾选改选项。
- Optimize Mesh:推荐启用,可以提升GPU性能。
- Normals:如果你的模型没有法线信息,将其设为None,可以减小模型大小。 OptimizeGameObjects:优化骨骼结点。 这个优化会大幅节省Animatior.Update这一项的耗时。 Anim.Compression: -Off -Keyframe Reduction减少关键帧 -Optimal最优的 RotationError:旋转误差。使用角度(degree)作为单位。 PositionError:位置误差。距离偏差的百分比(曲线调节前后的距离偏差与某距离值之比,取决于Unity内部实现),取值范围1~100,但实际可以高于100,并有作用。 ScaleError:缩放误差。距离偏差的百分比(曲线调节前后的距离偏差与某距离值之比,取决于Unity内部实现),取值范围1~100,但实际可以高于100,并有作用。 *建议调节该误差时,将调节前后的动画效果进行对比,使文件体积压缩的尽量小,同时使动画效果在视觉上偏差不会太大。 动画文件优化思路 1.使用Optimal压缩格式 2.缩减transform的float精度信息 默认存储每一帧transform信息的是10位精度的float格式数据。 建议通过导入器的OnPostprocessModel函数,缩减此数据为3位精度float,视觉效果基本一样。优化效果非常显著。
void OnPostprocessModel(GameObject g) {
List<AnimationClip> animationClipList = new List<AnimationClip>(AnimationUtility.GetAnimationClips(g));
if (animationClipList.Count == 0) {
AnimationClip[] objectList = UnityEngine.Object.FindObjectsOfType (typeof(AnimationClip)) as AnimationClip[];
animationClipList.AddRange(objectList);
}
foreach (AnimationClip theAnimation in animationClipList)
{
try
{
//去除scale曲线
foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings(theAnimation))
{
string name = theCurveBinding.propertyName.ToLower();
if (name.Contains("scale"))
{
AnimationUtility.SetEditorCurve(theAnimation, theCurveBinding, null);
}
}
//浮点数精度压缩到f3
AnimationClipCurveData[] curves = null;
curves = AnimationUtility.GetAllCurves(theAnimation);
Keyframe key;
Keyframe[] keyFrames;
for (int ii = 0; ii < curves.Length; ++ii)
{
AnimationClipCurveData curveDate = curves[ii];
if (curveDate.curve == null || curveDate.curve.keys == null)
{
continue;
}
keyFrames = curveDate.curve.keys;
for (int i = 0; i < keyFrames.Length; i++)
{
key = keyFrames[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;
}
curveDate.curve.keys = keyFrames;
theAnimation.SetCurve(curveDate.path, curveDate.type, curveDate.propertyName, curveDate.curve);
}
}
catch (System.Exception e)
{
Debug.LogError(string.Format("CompressAnimationClip Failed !!! animationPath : {0} error: {1}", assetPath, e));
}
}
}