当前位置: 首页 > article >正文

第四课 Animation动画资源导入设置检查与优化

上期我们学习了简单的Textures纹理的优化,接下来我们继续动画资源的优化

首先我们还是要把我们优化的目标重申一遍:

优化的目标

1.与原始动画无明显差异

2.曲线数量,常量曲线比重大为好

3.动画文件大小,动画文件在小几百K或更少合理,查过1M以上的动画文件待考虑

Unity动画的设置面板:

Rig标签页

1.Animation Type

None 无动画
Legacy 旧版动画,不要用
Generic  通用骨骼框架
Humanoid 人形骨骼框架

无动画选择None
非人形动画选择Generic
人形动画需要Kinematices或Animation Retargeting功能,或者没有有自定义骨骼对象时选择Humanoid Rig
其他都选择Generic Rig,在骨骼数差不多的情况下,Generic Rig会比Humanoid Rig省30%甚至更多的CPU的时间。

2.Skin Weights

默认4根骨头,但对于一些不重要的动画对象可以减少到1根,节省计算量

3.Optimize Bones

建议开启,在导入时自动剔除没有蒙皮顶点的骨骼

4.Optimize Game Objects

在Avatar和Animatior组件中删除导入游戏角色对象的变换层级结构,而使用Unity动画内部结构骨骼,消减骨骼transform带来的性能开销。可以提高角色动画性能, 但有些情况下会造成角色动画错误,这个选项可以尝试开启但要看表现效果而定。注意如果你的角色是可以换装的,在导入时不要开启此选项,但在换装后在运行时在代码中通过调用AnimatorUtility.OptimizeTransformHierarchy接口仍然可以达到此选项效果。

Animation

1.Resmple Curves

将动画曲线重新采样为四元数数值,并为动画每帧生成一个新的四元数关键帧,仅当导入动画文件包含尤拉曲线时才会显示此选项

2.Anim.Compression

- **Off** 不压缩,质量最高,内存消耗最大
- **Keyframe Reduction** 减少冗余关键帧,减小动画文件大小和内存大小。
- **Keyframe Reduction and Compression** 减小关键帧的同时对关键帧存储数据进行压缩,只影响文件大小。
- **Optimal**,仅适用于Generic与Humanoide动画类型,Unity决定如何进行压缩。

3.Animation Custom Properties

导入用户自定义属性,一般对应**DCC**工具中的**extraUserProperties**字段中定义的数据

动画曲线数据信息

- **Curves Pos:** 位置曲线
- **Quaternion:** 四元数曲线 **Resample Curves**开启会有
- **Euler:** 尤拉曲线
- **Scale:** 缩放曲线
- **Muscles:** 肌肉曲线,**Humanoid**类型下会有
- **Generic:** 一般属性动画曲线,如颜色,材质等
- **PPtr:**精灵动画曲线,一般2D系统下会有
- **Curves Total: **曲线总数
- **Constant:** 优化为常数的曲线
- **Dense:** 使用了密集数据(线性插值后的离散值)存储
- **Stream:** 使用了流式数据(插值的时间和切线数据)存储

优化思路

1.使用Optimal压缩格式
2.去除动画文件的scale信息
对于一般的人形动画需求,不会有模型骨骼scale变化的情况。
因此我们可以把动画信息的scale部分去除,可以节约一部分大小。
3.缩减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));
		}
	}
}

今天是2024年11月23日

重复一段毒鸡汤来勉励我和你

你的对手在看书

你的仇人在磨刀

你的闺蜜在减肥

隔壁的老王在练腰

而你在干嘛?


http://www.kler.cn/a/407420.html

相关文章:

  • 相机网卡开启巨型帧和关闭节能模式方法
  • 【MySQL】MySQL数据库基础
  • C# NetworkStream用法
  • java实现小程序接口返回Base64图片
  • Diving into the STM32 HAL-----DAC笔记
  • 自制游戏:监狱逃亡
  • Flink转换算子——flatMap/map/filter/keyby/reduce综合练习
  • Spring Boot 动态数据源切换
  • apache、iis规则屏蔽拦截ClaudeBot等蜘蛛爬虫抓取网页
  • 营销的本质
  • 3、集线器、交换机、路由器、ip的关系。
  • 传奇996_36——背包图标,物品位置问题
  • Hive分区的种类 分区关联数据的三种方式
  • Pinia 实战教程:构建高效的 Vue 3 状态管理系统
  • 鸿蒙学习笔记:ArkUI概述
  • 从搭建uni-app+vue3工程开始
  • 现代密码学
  • 【Linux庖丁解牛】—软件安装vim!
  • Spring Boot 入门指南:从零开始搭建你的第一个应用
  • Python数据结构之链表
  • 【计算机网络】物理层
  • C语言:字符串
  • 【C++笔记】list使用详解及模拟实现
  • eduSRC挖洞思路
  • Linux基础05
  • MySQL 三大日志详解