早期在动画控制这里经常遇到这样的问题,例如有一个角色,我们想让他执行wave的挥手动画,我们一般会调用
animator.SetInteger("wave", 1);
我们希望动画wave播放完毕后要退出。可以制作如下:
有经验的朋友知道,这样直接执行的话会出现反复挥手的动画调用,因为动画变量wave已经被改成了1。
在进入Exit后回到Default State后,因为wave是1,所以又进入了wave。
发现有的初学者在游戏业务脚本中去控制wave的关闭,例如延迟一个时间,然后再次调用
animator.SetInteger("wave", 0);
这样的确也是一个办法,但是这样稍微复杂一点的动画控制起来就很麻烦,特别是做动画的动画师也没办法自己调试动画,就非要程序的介入, 特别是对不会写代码的动画师来说更是如此。
本来是个很简单的东西,发现很多初学者不知道,这里就分享出来。利用StateMachineBehaviour脚本来制作。
先分享一个我早期的一个脚本,可以借鉴一下:
using UnityEngine;
using System.Collections;
//用来控制参数状态 add by lpj thinbug 2016/6/3
// Input state
[System.Serializable]
public struct BoolData
{
public string name;
public bool data;
}
[System.Serializable]
public struct FloatData
{
public string name;
public float data;
}
[System.Serializable]
public struct IntData
{
public string name;
public int data;
}
public class TBAnimatorParmChange : StateMachineBehaviour
{
public BoolData[] BoolExit;
public FloatData[] FloatExit;
public IntData[] IntExit;
public BoolData[] BoolEnter;
public FloatData[] FloatEnter;
public IntData[] IntEnter;
//OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
int i;
for (i = 0; i < BoolEnter.Length; i++)
{
animator.SetBool(BoolEnter[i].name, BoolEnter[i].data);
}
for (i = 0; i < FloatEnter.Length; i++)
{
animator.SetFloat(FloatEnter[i].name, FloatEnter[i].data);
}
for (i = 0; i < IntEnter.Length; i++)
{
animator.SetInteger(IntEnter[i].name, IntEnter[i].data);
}
}
// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
//override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
// OnStateExit is called when a transition ends and the state machine finishes evaluating this state
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
int i;
for (i = 0; i < BoolExit.Length; i++)
{
animator.SetBool(BoolExit[i].name, BoolExit[i].data);
}
for (i = 0; i < FloatExit.Length; i++)
{
animator.SetFloat(FloatExit[i].name, FloatExit[i].data);
}
for (i = 0; i < IntExit.Length; i++)
{
animator.SetInteger(IntExit[i].name, IntExit[i].data);
}
}
// OnStateMove is called right after Animator.OnAnimatorMove(). Code that processes and affects root motion should be implemented here
//override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
// OnStateIK is called right after Animator.OnAnimatorIK(). Code that sets up animation IK (inverse kinematics) should be implemented here.
//override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
}
我们来看看如何使用吧。
第一步:因为我们希望在进入Wave动画后就可以关闭变量wave了,所以我们点击Wave State,点击按钮Add Behaviour,如图:
这里就会出现我刚才添加的脚本TBAnimatorParmChange。
因为wave是int型变量,所以我们在Int Enter事件中添加
意思就是在OnStateEnter的时候,把wave变量改为0,这样wave运行完毕后就直接退出不会再次进入了。
我们来看看效果:
当我把变量wave改为1后,动画进入Wave后wave变量又称为了0。
这里就是StateMachineBehaviour最简单的用法。