欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

FSM状态机

程序员文章站 2024-03-19 18:17:58
...

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));
    }
}

FSM状态机

FSM状态机

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;
    }
}


相关标签: FSM状态机