采用状态模式的FSM有限状态机

4 篇文章 0 订阅

首先我们要确定,基于状态模式的状态模式的FSM有限状态机有三个部分:分别是状态机本身,状态,状态之间的转换。这三个部分都需要封装成对象,以便降低代码之间的耦合度。

1.FSM
public enum RoleState
{
    Idle,
    Walk,
    Jump,
    Attack,
    Dead,
    PickUp,
}


public class FSM //不要继承MonoBehaviour
{
    //状态机运行时状态参数,当前状态,上一个状态。
    public StateBase curState { get; private set; }
    public StateBase lastState { get; private set; }
    //用字典记录状态机中所有的状态
    private Dictionary<RoleState, StateBase> states = new Dictionary<RoleState, StateBase>();
 
 
    //状态机整体的参数
    private StateBase defaultState;//状态机默认状态,也即第一个状态
    private StateBase exitState;//状态机退出状态,也即最后一个状态
 
    public void Init(StateBase defaultState)//状态机初始化
    {
        this.defaultState = defaultState;
        curState = defaultState;
        curState.Enter();
    }
 
    public void Update(string input)//状态机的执行,即切换状态
    {
        if(curState == null)
            return;
        StateBase nextState = curState.HandleInput(input);//处理当前输入,获取下一状态
        if (nextState != curState && nextState != null)
        {
            curState.Exit();
            lastState = curState;
            curState = nextState;//状态切换
            curState.Enter();
        }
        curState.Update();
    }
 
    public void AddState(RoleState stateId,StateBase state)
    {
        states.Add(stateId,state);
    }
 
    public bool Remove(RoleState stateId)
    {
        if (states.ContainsKey(stateId))
        {
            states.Remove(stateId);
            return true;
        }
 
        return false;
    }
 
    public StateBase GetState(RoleState stateId)
    {
        if (states.ContainsKey(stateId))
            return states[stateId];
        return null;
    }

}

2.状态的基类

public class StateBase//可以是接口,也可以是基类,具体使用哪个看情况
{
    public RoleState stateId { get;private set; }//状态ID
    public FSM parent { get;private set; }//属哪个状态机
 
    public StateBase(FSM parent, RoleState stateId)
    {
        this.parent = parent;
        this.stateId = stateId;
    }  

     //状态的全部转换,需要在Player对象类中初始化生成并添加进对应的状态中
    public List<TransitionBase> transitions = new List<TransitionBase>();
    public void AddTransition(TransitionBase transition)
    {
        transitions.Add(transition);
    }

  
    public virtual void Enter(){}//进入状态时进行的动作
    public virtual void Exit(){}//退出状态时进行的动作
 
    //在这个状态内要执行的操作
    public virtual void Update(){}//在状态内执行相关输出
 
    public virtual StateBase HandleInput(string input)//在当前状态内处理输入
    {
        foreach (TransitionBase item in transitions)//判断该输入是否满足某个转移
        {
            if (item.fromState != this)
            {
                continue;
            }
            if(item.CanTransition(input))
            {
                return item.toState;
            }
        }
        return null;
    }
}
3.状态转换的基类

public class TransitionBase
{
    //从某个状态转换到另一个状态
    public StateBase fromState;
    public StateBase toState;
 
    public TransitionBase(StateBase fromState, StateBase toState)
    {
        this.fromState = fromState;
        this.toState = toState;
    }
 
    public virtual bool CanTransition(string input)
    {
        //在这里处理输入,判断一个状态是否能进入另一个状态
        return true;
    }
 
}

状态机的使用

public class Player:MonoBehaviour
{
    private FSM fsm;
 
    public Player()
    {
        //在构造函数中实例化状态机,并将实例化后的状态加入状态机中,然后根据需要的状态转移图将转移类加入状态中,最后设置状态机的初始状态。
    }
 
    public void Update()
    {
        fsm.Update(input);
    }
 
    private string input;
    public void SetInput(string input)
    {
        this.input = input;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值