State machine behaviours可以挂载在Animator Controller里面的动画状态上。把这个脚本挂在动画状态上,可以很清楚的知道状态控制器在执行什么状态。
下面的AnimationStateCb类即继承自StateMachineBehaviour
在inspector中点击Add Behaviour,选择新建脚本,就会自动继承自StateMachineBehaviour。
这些函数有三个参数传递给他们: Animator, AnimatorStateInfo和 layer 索引。
override public void OnStateEnter (Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
player = GameObject.Find(“Player”);
}
Animator 动画参数是特定的animator ,是这个状态机行为的引用。例如,这可以用于设置 动画参数的值只能在此状态下,例如,用于blend tree混合树。
AnimatorStateInfo 是状态机的行为是对state 的当前信息。它是相当于writing animator.GetCurrentStateInfo(layerIndex); 这可以涉及该clip剪辑的正常的时间的操作很有用。
LayerIndex 是状态机行为状态的layer 层。例如,0为基底图层,1用于第一个 等等。
类似MonoBehaviours, StateMachineBehaviour 函数在特定情况下被调用
OnStateEnter 正在played的状态的第一帧被调用。
OnStateUpdate MonoBehaviour Updates 更新后被调用,每一帧animator 是playing 时这个行为的状态。
OnStateExit 转换到另一个状态的最后一帧 被调用。
OnStateMove 在OnAnimatorMove之前被调用 ,将在MonoBehaviours 调用之前的每个帧的state playing 。当调用 OnStateMove 时,它将停止 MonoBehaviours 调用 OnAnimatorMove。
OnStateMachineEnter 在 animator plays 的内容的一个子状态机的第一帧上被调用。
OnStateMachineExit 从一个子状态机过渡的最后一帧上被调用。
public class AnimationStateCb : StateMachineBehaviour {
// 进入动画状态
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
base.OnStateEnter(animator, stateInfo, layerIndex);
Role role = RoleService.Instance.GetRunningRole();
if (role == null) return;
//攻击部分
if (stateInfo.shortNameHash == AnimatorNameDefine.Attack1)//攻击
{
role.SetCurAnimState(EnumDataDef.AnimState.Attack1); // 设置当前动画状态
}
}
}
public class AnimatorNameDefine
{
public static readonly int Attack1 = Animator.StringToHash("atk1");
}
用stateInfo.IsName("atk1");判断动画状态也是可以的
要正确理解 MonoBehaviours 和 StateMachineBehaviours 之间的区别是有必要了解一下,assets 资产和scene objects场景对象之间的区别。
场景对象只存在于一个单一的场景。这些包括GameObjects 游戏对象和它们的components 组件以及prefabs预置的实例。Assets 存在project 中,可以在任何场景中引用。这些包括动Animator Controllers, prefab assets 和 StateMachineBehviours。由于scene 与一个特定的对象可能不会loaded加载,asset 资产不能引用一个场景对象。由于asset 资产总是存在于project中,场景objects 可以引用assets。
请记住 state machine behaviours 是 Assets,它们不能储存scene objects的引用。为了在state machine behaviour 状态机行为中引用一个scene object ,该引用的对象必须能被 找到或传递到状态机行为。举个例子:
override public void OnStateEnter (Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
player = GameObject.Find(“Player”);
}
(State machine behaviours)状态机行为他们的创建方式不像MonoBehaviours 。当MonoBehaviours 实例被创建并被添加到一个游戏对象上因此成为场景对象,StateMachineBehaviour 类派生自 ScriptableObject。因此,状态机行为是 assets,不是场景对象。 这意味着状态机行为要想存在在一个场景中,状态机行为在运行时自动创建实例 ,在Animator’s 的内部Awake 调用。这意味着在 MonoBehaviour 的 Awake 函数期间 找到 对它们的引用是不建议,因为它将产生不可预知的结果。
在MonoBehaviour中 要获得对 StateMachineBehaviour 的引用 ,可以使用任何 animator.GetBehaviour<>() 或者 animator.GetBehaviours<>(). GetComponent<>() and GetComponents<>().的功能类似 。GetBehaviour 将在animator上找到的第一个实例 返回指定的 StateMachineBehaviour 。GetBehaviours 将返回找到的指定类型的所有 StateMachineBehaviours 的数组。由于不能保证状态机行为已在Awake中实例化,应在Start 函数值红 调用这些函数。
这里是单一的 StateMachineBehaviour 和 MonoBehaviour 之间的查找 引用一个短的例子。
public class ExampleMonoBehaviour : MonoBehaviour
{
private Animator animator;
private ExampleStateMachineBehaviour exampleSmb; // Reference to a single StateMachineBehaviour.
void Awake ()
{
animator = GetComponent ();
}
void Start ()
{
// Find a reference to the ExampleStateMachineBehaviour in Start since it might not exist yet in Awake.
exampleSmb = animator.GetBehaviour ();
// Set the StateMachineBehaviour's reference to an ExampleMonoBehaviour to this.
exampleSmb.exampleMb = this;
}
}
public class ExampleStateMachineBehaviour : StateMachineBehaviour
{
public ExampleMonoBehaviour exampleMb;
}
原文:https://blog.csdn.net/u010019717/article/details/44760683