前言
当我们有很多相似的预制体并且他们的动画都相同的时候,若我们创建多个多个Animation Clip或者Animation Controller (特别是对于多个控制器来说都有相同逻辑状态的时候) 就会浪费很多空间。为此,我们可以制作一个框架从而替换里面的参数 *(Animation Clip)*来节省空间与时间。
如何将AnimationController作为模板
若我们的Animation Controller有可以复用的逻辑状态时 (比如循环播放,或者触发器触发动画等逻辑状态),那么就可以通过AnimationOverrideController来更改AnimationClip来达到复用的目的。
比如触发器的状态机:
这个状态机通过设置trigger参数达到触发动画的目的,大部分简单的触发器动画都可以用此控制器框架,那么这个AnimationController只创建一个作为模板就好,我们只需要替换Motion状态的AnimationClip (Empty是一个创建的空动画,因为AnimationOverrideController需要替换的是存在的动画) 即可。
创建AnimationOverrideController并且替换Empty
然后将创建的AnimationOverrideController替换掉原来的AnimationController即可。
代码动态实现
利用AnimationOverrideController组件可以替换状态机中的动画剪辑,从而达到使用框架的目的,但是创建多个AnimationOverrideController也是很麻烦并且也会占用空间,那么我们可以通过代码来实现这个功能,从而不在Assets中创建AnimationOverrideController:
using UnityEngine;
public class ACMotion : MonoBehaviour
{
public AnimationClip Motion
{
get
{
return motion;
}
set
{
motion = value;
ApplyMotion();
}
}
[SerializeField]
private AnimationClip motion;
private Animator animator;
void Awake()
{
animator = GetComponent<Animator>();
ApplyMotion();
}
void ApplyMotion()
{
if (motion != null)
{
AnimatorOverrideController animatorOverrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);
//animatorOverrideController[]中需要传入AnimationClip或者剪辑的名字字符串
//若是需要替换多个剪辑则可以使用键值对的方法查找替换
animatorOverrideController[animatorOverrideController.animationClips[0]] = motion;
animator.runtimeAnimatorController = animatorOverrideController;
}
}
}
该脚本需要有组件Animator,并且添加AnimatorController,AnimatorController还是上述例子的Trigger框架,把要替换的AnimationClip拖到脚本里的Motion上即可。
也可以动态通过ACMotion脚本里的属性Motion动态修改:
void ChangeMotion()
{
ACMotion acMotion = GetComponent<ACMotion>();
acMotion.Motion = GetAnimationClip();
}
以上例子演示了状态机模板中只需替换一个动画的情况,对于需要替换多个剪辑的情况可也以通过AnimationOverrideController的剪辑替换功能实现,利用AnimationOverrideController组件和脚本替换AnimationClip就可以实现动画状态机模板制作功能。
关于AnimationOverrideController可以参考这两篇文章:
unity Animator Override Controller的使用
[Unity]运行时用AnimatorOverrideController动态加载动画片段