Unity中动画的无损压缩(一)
此文参考了:前言:虽然动画压缩早是一个老生常谈的话题,且很多动画制作软件都有着对动画压缩的一套很完备的策略,其中也包括游戏引擎Unity。Unity在动画压缩方面提供了一套方案,但是有损的。本篇讲述如何在Unity中实现动画的无损压缩。希望你看了能有很大帮助o(∩_∩)o 由于制作动画的同学水平参差不齐,实现同一效果的方式也千变万化,所以导致个项目的动画文件及其繁杂。随着项目不断迭代,动画这部分慢慢的会占据着巨大的一部分资源,而且还不敢随便碰,不然容易导致动画文件损坏。
在谈动画压缩方案之前我们先聊聊Unity中的动画系统。
Unity中的动画系统:
在Unity中,大部分角色的动画都是Animation。Animation是由Animation Curve来表示的,大部分项目中的角色动画一般Curve只有Position,Rotation和Scale。
一个复杂的角色动画
每条曲线上都有着N个KeyFrame,这些关键帧存储着顶点变化,位移变换等重要信息。
动画文件的存储形式是.anim文件,用Notepad打开可以看到其详细信息。
某一关键帧的信息
可以看到一个KeyFrame中存储了Value、inSlope、outSlope信息。
Unity中对于KeyFrame的处理其实就是相邻读取,线性插值。读到这里聪明的你肯定会说了:这里的KeyFrame数据精度这么高,直接对他裁剪不就优化了吗?
在这里,我可以明确的告诉你,这种方法是不起任何作用的!
如果你真的这么做了,那么你会惊喜的发现.anim文件在磁盘上减少了很多占用,但他并不会对我们打包后的apk有任何帮助。
为什么呢?因为Unity会对.anim的文件先进行裁剪和加工,之后打包成Asset Bundle,而Asset Bundle是二进制文件,同一个Float,不管精度如何它都占用同样的大小,所以也就失去了意义。
虽然裁剪精度是无用功,但我们可以裁减掉.anim文件中无用的Scale曲线,减少包体和少部分的数据处理耗时。
在一般的角色动画制作流程中,几乎很少有人会对骨骼来进行Scale缩放,尤其是对于手游来说,很少有人会用骨骼的Scale来实现效果的。因为类似的效果完全可以用周围顶点偏移来完成,操作方便且运算量小,除非一些及其特殊的需求,才会偶尔用到骨骼Scale。
一个无用的Scale曲线
那么我们就可以来删减.anim文件中所有无用的Scale曲线。这个操作是不会对动画效果有任何损失的,做到真正意义上的无损压缩。
具体实现:
第一步是要找到文件夹下的所有.anim文件。
通过递归找到所有的anim文件
找到所有的.anim文件后对其进行遍历,逐个优化。这里我们只处理Scale曲线。
过滤掉position和rotation曲线
我们要先收集所有的Constant的Scale曲线。这里我记录第一帧的Value,如果该曲线不是Constant那么曲线上的Value一定有不同的,所以对曲线上的KeyFrame Value逐个比对即可。
找到所有的!Constant曲线
之后进行剔除,注意这里foreach遍历的是所有的曲线(包括Position、Rotation),这里还需要单独对Scale检索一次。
删除!Constant曲线
测试:
这里我们拿一个较为复杂的动画文件来做测试。
压缩前占用比
压缩前的曲线细则
可以看到几乎每个骨骼下都有一个Scale
压缩后占用比
压缩后的曲线细则
可以看到还是删除了不少的Scale曲线,Constant数量由357->138,裁减了进220条无用曲线,内存占用也少了2.6KB,这对于一个无损压缩方案来说还是很可观的。
我用此方法在王者荣耀的工程里对所有英雄的动画文件进行压缩,是没有任何问题的。足以说明此方案的可行性。
要说明的一点:
使用了Scale裁剪策略后,.anim文件会有巨量的增长。
压缩前
压缩后
那么我们来看看到底增加了些什么
压缩前的.anim文件
压缩后的.anim文件
压缩前
压缩后
m_EditorCurves和m_EulerEditorCurves部分的信息是编辑器内记录动画的信息,是冗余的,删除的话也没有任何影响,所以这部分增量是可以忽略的。
除此以外还有
压缩后会增加的字段
这里需要注意一下,这里的.anim文件大小只是在磁盘中的占用,上文也提到过,Unity打包Asset Bundle的时候会进行裁剪,所以这里的增量是可以忽略的。
页:
[1]