上篇文章讲了通用状态机的实现(文末),这次讲讲如何在实际情况中去使用。这次先做一个简单的控制Animator
的状态机。
鉴于我用来做动画的模型只有Idle、Run、Die三种状态,所以就较为简单,这次只是教基本的使用,下次讲如何做AI巡逻。
动画机不介绍了,这个不会的先去学前面的教程,搭建过程略过。
如果还有走路的动画可以用x做个简单的混合树,还有这里做的不太严谨,用于练习的例子就不那么严谨了。x表示当前速度,IsDie表示是否死亡,动画机部分完成。
角色部分的话需要挂载character controller
和Animator
组件,同时记得挂载好脚本组件。
先声明枚举,这里有三种状态,实际可划分为两种:Movement和Die。枚举完工。
public enum FSMCharacterState
{
Movement,
Die
}
为了严谨先创建一个鹿的状态机基类,继承自状态机基类(具体看我上次文章,末尾有传送门),因为用animator
控制动画,character controller
控制移动,所以需要声明这两个字段,同时在构造函数里传递进来并赋值,鹿的状态机基类也完成了。
public abstract class FSMDeer : FSMBase<FSMCharacterState>
{
protected Animator deerAnimator;
protected CharacterController characterController;
protected FSMDeer(FSMManagerBase<FSMCharacterState> manager,GameObject deer) : base(manager)
{
deerAnimator = deer.GetComponent<Animator>();
characterController = deer.GetComponent<CharacterController>();
}
}
接下来该实现FSMDeerMove
与FSMDeerDie
这两个类了,移动要用character controller
实现,所以就需要重新声明OnAnimatorMove
这个方法来覆盖动画片段里的位移,这里先说一下构造函数和OnEnter两个的区别,构造函数是new时只生成一次,而OnEnter是每次进入此状态时就调用一次,与OnEnable函数相似,每次激活时调用,所以不用每次赋值的全局变量就写在构造函数里就行。
移动时肯定需要速度来控制,所以声明一个常量speed,而.characterController.Move方法需要传递一个Vec3类型的参数,为了避免gc,故声明全局变量moveStepSize,在构造函数里new,在使用时调用set方法。
public class FSMDeerMove : FSMDeer
{
private static readonly int X = Animator.StringToHash("X");
private Vector3 _moveStep;
private sbyte _speed = 8;
public FSMDeerMove(FSMManagerBase<FSMCharacterState> manager,GameObject deer) : base(manager,deer)
{
ClassState = FSMCharacterState.Movement;
_moveStep = new Vector3();
}
public sealed override FSMCharacterState ClassState {
get; protected set; }
public override