FSM状态机

StateBase类、StateTemplate类、Idel类、PlayerCtrl类

StateBase:状态基类,标明状态的3个阶段,以及状态ID,并维护一个用来管理自己的状态机。

public class StateBase : MonoBehaviour {

	//状态的ID
    public int ID { get;set;}
    
    //状态机
    public StateMachine machine;

    public StateBase(int id) {
        this.ID = id;
    }

    //状态的三个阶段
    public virtual void OnEnter(params object[] args) { }
    public virtual void OnStay(params object[] args) { }
    public virtual void OnExit(params object[] args) { }

}

StateTemplate:继承自StateBase,维护一个状态的拥有者(因为不同角色都有自己的动画要控制)

public class StateTemplate<T> : StateBase {

    //定义状态的拥有者
    public T m_owner;

    public StateTemplate(int id, T o) : base(id) {
        this.m_owner = o;
    }
}

StateMachine:用来管理状态的存储、切换、保持

public class StateMachine : MonoBehaviour {

    public Dictionary<int, StateBase> m_StateCache;

    //用来保存当前角色执行的状态
    public StateBase m_CurrentState;
    //用来保存当前角色执行的上一个状态
    public StateBase m_PreviousState;

    public StateMachine(StateBase beganState) {
        m_PreviousState = null;
        m_CurrentState = beganState;

        m_StateCache = new Dictionary<int, StateBase>();

        RegisterState(beganState);//把开始状态注册进字典
        beganState.OnEnter();//开始状态的执行
    }

    //存储状态
    public void RegisterState(StateBase aState) {
        int id = aState.ID;

        if (m_StateCache.ContainsKey(id)) {
            return;
        }
        //如果当前字典里没有这个状态,则添加进来
        m_StateCache.Add(id,aState);
        //表示当前状态由谁来存储、管理
        aState.machine = this;
    }

    //保持状态
    public void FSMUpdate() {
        if (m_CurrentState != null) {
            m_CurrentState.OnStay();
        }
    }

    //切换状态
    public void TranslateToState(int id,params object[] args) {
        int keyID = id;
        if (!m_StateCache.ContainsKey(keyID)) return;

        m_PreviousState = m_CurrentState;
        m_CurrentState = m_StateCache[keyID];
        m_CurrentState.OnEnter();//让刚切换的状态进入
    }
}

PlayerCtrl:维护属于他自己的状态机,并在Update中去控制动画的播放(其实是通过状态机来控制状态注册,转换和播放)

public enum PlayerStates { 
    Idle,
    Attack,
    Run
}
public class PlayerCtrl : MonoBehaviour {

    private StateMachine m_StateMachine;
    public Animation ani;
    public PlayerStates state = PlayerStates.Idle;

    void Awake() {
        ani = GetComponent<Animation>();
    }
    void Start() {
        m_StateMachine = new StateMachine(new IdelState(0, this));
        m_StateMachine.RegisterState(new AttackState(1,this));
    }
}



Idel:

public class IdelState : StateTemplate<PlayerCtrl> {

    public IdelState(int id, PlayerCtrl owner):base(id,owner) { 
        
    }

    public override void OnEnter(params object[] args)
    {
        base.OnEnter(args);
        m_owner.ani.Play("Idle");
    }

    public override void OnStay(params object[] args)
    {
        base.OnStay(args);
        if (!m_owner.ani.IsPlaying("Idle")) {
            OnExit();
        }
    }

    public override void OnExit(params object[] args)
    {
        base.OnExit(args);
    }
}

Attack:

public class AttackState : StateTemplate<PlayerCtrl> {

	public AttackState(int id, PlayerCtrl owner):base(id,owner) { 
        
    }

    public override void OnEnter(params object[] args)
    {
        base.OnEnter(args);
        m_owner.ani.Play("Attack");
    }

    public override void OnStay(params object[] args)
    {
        base.OnStay(args);
        if (!m_owner.ani.IsPlaying("Attack"))
        {
            OnExit();
        }
    }

    public override void OnExit(params object[] args)
    {
        base.OnExit(args);
        m_owner.state = PlayerStates.Idle;
    }
}


猜你喜欢

转载自blog.csdn.net/ai_little_ai/article/details/80699553