一. 状态机监听
- AnimStateHook - 状态机钩子
- 继承自 Unity 的 StateMachineBehaviour,附加到 Animator Controller 的状态上
- 拦截 Animator 的三个生命周期回调:OnAnimEnter、OnAnimUpdate、OnAnimExit
- 从 Animator 所在 GameObject 获取 AnimEventDispatcher 组件并转发事件
public class AnimStateHook : StateMachineBehaviour
{
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex, AnimatorControllerPlayable controller)
{
AnimEventDispatcher call = animator.gameObject.GetComponent<AnimEventDispatcher>();
if (call != null)
{
call.OnEnterChannel(animator, stateInfo, layerIndex);
}
}
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex, AnimatorControllerPlayable controller)
{
AnimEventDispatcher call = animator.gameObject.GetComponent<AnimEventDispatcher>();
if (call != null)
{
call.OnUpdateChannel(animator, stateInfo, layerIndex);
}
}
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex, AnimatorControllerPlayable controller)
{
AnimEventDispatcher call = animator.gameObject.GetComponent<AnimEventDispatcher>();
if (call != null)
{
call.OnExitChannel(animator, stateInfo, layerIndex);
}
}
}
- AnimEventDispatcher - 事件分发器
- 作为 MonoBehaviour 组件挂载在有 Animator 的 GameObject 上, 提供外部监听方法
- 接收 AnimStateHook 的回调并广播对应事件
public class AnimEventDispatcher : MonoBehaviour
{
public Action<int, float> OnEnterEvent;
public Action<int, float> OnUpdateEvent;
public Action<int, float> OnExitEvent;
public void OnEnterChannel(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
OnEnterEvent?.Invoke(stateInfo.shortNameHash, stateInfo.normalizedTime);
}
public void OnUpdateChannel(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
OnUpdateEvent?.Invoke(stateInfo.shortNameHash, stateInfo.normalizedTime);
}
public void OnExitChannel(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
OnExitEvent?.Invoke(stateInfo.shortNameHash, stateInfo.normalizedTime);
}
}
- 总结: 如上提供了一种监听Animator状态变化的监听方法, 入状态进入(Enter), 状态Update(Update), 状态退出(Exit)注意事项
- normalizedTime为百分比时间
- 两个相邻状态A -> B, Unity无法保证A的退出先执行, B的进入后执行, 可能先执行B的进入,再执行A的退出也未可知