Unity---游戏设计模式(8)之状态模式(有限状态机FSM)




概述参考请看 参考博客

1、原型

原型代码


/// <summary>
/// 转换条件(就是UML图中的箭头)
/// </summary>
public enum Transition
{
    NullTransition = 0,
}
/// <summary>
/// 要转换到的状态(就是箭头所指的状态)
/// </summary>
public enum StateID
{
    NullStateID = 0,
}

/// <summary>
/// 代表一个角色状态
/// </summary>
public abstract class FSMState
{
    //存储这个状态的所有转变条件和转变后的状态
    protected Dictionary<Transition, StateID> mMap = new Dictionary<Transition, StateID>();
    //表示此类为哪个状态
    protected StateID mStateID;
    public StateID StateID { get { return mStateID; } }

    /// <summary>
    /// 向字典中添加状态转变条件
    /// </summary>
    public void AddTransition(Transition trans, StateID id)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError("FSMState ERROR: NullTransition 不可添加");
            return;
        }

        if (id == StateID.NullStateID)
        {
            Debug.LogError("FSMState ERROR: NullStateID 不可添加");
            return;
        }

        if (mMap.ContainsKey(trans))
        {
            Debug.LogError("FSMState ERROR: State " + mStateID.ToString() + "已经有这个转换条件" + trans.ToString());
            return;
        }
        mMap.Add(trans, id);
    }

    /// <summary>
    /// 向字典中删除状态转变条件
    /// </summary>
    public void DeleteTransition(Transition trans)
    {
        if (mMap.ContainsKey(trans) == false)
        {
            Debug.LogError("删除转换条件时,转换条件" + trans + "不存在");
            return;
        }
        mMap.Remove(trans);
    }

    /// <summary>
    /// 根据状态转变条件得到状态
    /// 根据key得到value
    /// </summary>
    public StateID GetOutputState(Transition trans)
    {
        if (mMap.ContainsKey(trans))
        {
            return mMap[trans];
        }
        return StateID.NullStateID;
    }

    /// <summary>
    /// 进入状态时的执行
    /// </summary>
    public virtual void DoBeforeEntering() { }

    /// <summary>
    /// 离开状态时的执行
    /// </summary>
    public virtual void DoBeforeLeaving() { }

    /// <summary>
    /// 在这个状态时所要执行的游戏逻辑
    /// </summary>
    public abstract void Act(GameObject player, GameObject npc);

    /// <summary>
    /// 判断当前状态是否需要转变为其他状态
    /// </summary>
    public abstract void Reason(GameObject player, GameObject npc);

}

/// <summary>
/// 状态管理系统
/// </summary>
public class FSMSystem
{
    private List<FSMState> mStates;

	private StateID mCurrentStateID;
    public StateID CurrentStateID { get { return mCurrentStateID; } }
    private FSMState mCurrentState;
    public FSMState CurrentState { get { return mCurrentState; } }

    public FSMSystem()
    {
        mStates = new List<FSMState>();
    }

    /// <summary>
    /// 添加状态
    /// </summary>
    public void AddState(FSMState state)
    {
        if (state == null)
        {
            Debug.LogError("SoldierFSMSystem Error,状态不能为空");
            return;
        }
        if (mStates.Count == 0)
        {
            mStates.Add(state);
            mCurrentState = state;
			mCurrentStateID = state.StateID;
            return;
        }
        //判断此状态是否已经存在
        foreach (FSMState s in mStates)
        {
            if (s.StateID == state.StateID)
            {
                Debug.LogError("要添加的状态ID[" + s.StateID + "]已经添加");
                return;
            }
        }
        mStates.Add(state);
    }

    /// <summary>
    /// 删除状态
    /// </summary>
    public void DeleteState(StateID id)
    {
        if (id == StateID.NullStateID)
        {
            Debug.LogError("要删除的状态ID为空" + id);
            return;
        }
        foreach (FSMState s in mStates)
        {
            if (s.StateID == id)
            {
                mStates.Remove(s);
                return;
            }
        }
        Debug.LogError("要删除的StateID不存在集合中:" + id);
    }

    /// <summary>
    /// 执行状态的转变
    /// </summary>
    public void PerformTransition(Transition trans)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError("要执行的转换条件为空 : " + trans);
            return;
        }
        StateID nextStateID = mCurrentState.GetOutputState(trans);
        if (nextStateID == StateID.NullStateID)
        {
            Debug.LogError("在转换条件 [" + trans + "] 下,没有对应的转换状态");
            return;
        }
		
		mCurrentStateID = nextStateID;
        foreach (FSMState s in mStates)
        {
            if (s.StateID == nextStateID)
            {
                mCurrentState.DoBeforeLeaving();
                mCurrentState = s;
                mCurrentState.DoBeforeEntering();
                return;
            }
        }
    }
}
posted @ 2019-10-17 17:26  Fflyqaq  阅读(493)  评论(0编辑  收藏  举报