U3L18-8——Statemachinebehaviour 状态机行为脚本

状态机行为脚本

状态机行为脚本时一类特殊的脚本,继承指定的基类,它主要用于关联到状态机中的状态矩形上
我们可以按照一定规则编写脚本,当进入、退出、保持在某一个特定状态时我们可以进行一些逻辑处理
简单解释就是为Animator Controller状态机窗口中的某一个状态添加一个脚本
利用这个脚本我们可以做一些特殊功能
比如

  1. 进入或退出某一状态时播放声音
  2. 仅在某些状态下检测一些逻辑,比如是否接触地面等等
  3. 激活和控制某些状态相关的特效

本章代码关键字

1
2
3
4
5
6
7
8
9
10
StateMachineBehaviour        //如果想要使一个脚本作为状态机脚本,则必须要继承这个基类
OnStateEnter() { } //进入状态时,第一个Update中调用
OnStateExit() { } //退出状态时,最后一个Update中调用
OnStateIK() { } //OnAnimatorIK后调用
OnStateMove() { } //OnAnimatorMove后调用
OnStateUpdate() { } //除第一帧和最后一帧,每个Update上调用
OnStateMachineEnter() { } //子状态机进入时调用,第一个Update中调用
OnStateMachineExit() { } //子状态机退出时调用,最后一个Update中调用
AnimatorStateInfo //动画状态信息类,可以从这个类获取该脚本依附的状态信息,例如状态名字等
stateInfo.IsName() //可以通过该方法来使用名字确认是否为某个状态

如何使用状态机脚本

  1. 新建一个脚本 继承StateMachineBehaviour基类

    1
    public class Lesson57 : StateMachineBehaviour { }
  2. 实现其中的特定方法进行状态行为监听

  3. 处理对应逻辑

状态机脚本相关内容

脚本必须继承 StateMachineBehaviour基类 才能作为状态机脚本使用

1
public class Lesson57 : StateMachineBehaviour { }

方法较多,但是没必要每个都记住,直接Override重写,然后在弹出的菜单里自动补全即可
image

每个重写的方法都会自动出现 base.重写的方法(参数)
但是实际上基类里并没有任何的实现,因此删去这句代码也不会出现什么问题

在状态机脚本类里声明公开变量,可以实现类似于在Inspector窗口上显示变量

image​​image

OnStateEnter()

进入状态时,第一个Update中调用

1
2
3
4
5
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (stateInfo.IsName("Idle"))
Debug.Log("进入了Idle状态");
}

OnStateExit()

退出状态时,最后一个Update中调用

1
2
3
4
5
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (stateInfo.IsName("Idle"))
Debug.Log("退出Idle状态");
}

OnStateIK()

在OnAnimatorIK后调用

1
2
3
4
public override void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateIK(animator, stateInfo, layerIndex);
}

OnStateMove()

在OnAnimatorMove后调用

1
2
3
4
public override void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateMove(animator, stateInfo, layerIndex);
}

OnStateUpdate()

除第一帧和最后一帧,每个Update上调用

1
2
3
4
5
6
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateUpdate(animator, stateInfo, layerIndex);
if (stateInfo.IsName("Idle"))
Debug.Log("处于Idle状态");
}

OnStateMachineEnter()

子状态机进入时调用,第一个Update中调用

1
2
3
4
public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
{
base.OnStateMachineEnter(animator, stateMachinePathHash);
}

OnStateMachineExit()

子状态机退出时调用,最后一个Update中调用

1
2
3
4
public override void OnStateMachineExit(Animator animator, int stateMachinePathHash)
{
base.OnStateMachineExit(animator, stateMachinePathHash);
}

AnimatorStateInfo

动画状态信息类,可以从这个类获取该脚本依附的状态信息,例如状态名字等

确认状态名字

可以通过该方法来使用名字确认是否为某个状态

1
2
if (stateInfo.IsName("Idle"))
Debug.Log("进入了Idle状态");

状态机行为脚本和动画事件如何选择

状态机行为脚本相对动画事件来说更准确
但是使用起来稍微麻烦一些

根据实际需求选择使用

例如,想要在动画中间触发事件可以使用动画事件,想要精确的在动画开始或者结束触发事件可以使用状态机行为脚本