FSM有限狀態機 ---C#、Unity -狀態模式

抽象類State 每一個狀態類都要繼承State 如 GameConnectStart GameConnectIng GameConnectERROR等狀態 實現抽象類的方法 在GameStateMachine來存儲每一個狀態 以便於尋找每一個狀態

public interface State//定義狀態接口
    {
        void Init();//初始化

        int GetCurrentStateId();//返回當前狀態Id

        void ComeEvent(State state);//進入狀態

        void LeaveEvent(State state);//離開狀態
    }

抽象類StateMachine 定義抽象接口

public interface StateMachine<T>//定義狀態機接口
    {
        T GetCurrentState();//返回當前狀態

        T GetPreviousState();//返回上個狀態

        void Register(T t);//註冊狀態

        void RemoveState(T t);//移除狀態

        void SwitchState(T t);//切換狀態
        
    }

狀態機GameStateMachine

public class GameStateMachine:StateMachine<State>//狀態機
    {
        public State CurrentState = null; //當前狀態
        public State PrevisousState = null;//上一個狀態

        public Dictionary<int, State> StateDt;//狀態存儲

        public GameStateMachine()
        {
            StateDt = new Dictionary<int ,State>();
        }

        public State GetCurrentState()
        {
            return CurrentState;//返回當前狀態
        }

        public State GetPreviousState()
        {
            return PrevisousState;//返回上一個狀態
        }

        public void Register(State t)
        {
            if (StateDt.ContainsKey(t.GetCurrentStateId()))//判斷註冊狀態是否是已經註冊  註冊過return
                return;

            StateDt.Add(t.GetCurrentStateId(),t);//添加狀態id和狀態信息
        }

        public void RemoveState(State t)
        {
            if (!StateDt.ContainsKey(t.GetCurrentStateId()))//判斷註冊狀態是否是已經註冊  沒註冊過return
                return;
            
            StateDt.Remove(t.GetCurrentStateId());//移除狀態id和狀態信息
        }

        public void SwitchState(State t)
        {
            if (!StateDt.ContainsKey(t.GetCurrentStateId())) //判斷當前狀態有沒有註冊
                return;

            if (CurrentState !=null)//判斷是否是第一次
            {
                if (CurrentState.GetCurrentStateId() == t.GetCurrentStateId())//判斷要切換的狀態和當前狀態是否是相同狀態
                    return;

                CurrentState.LeaveEvent(t);//當前狀態的離開方法
                PrevisousState = CurrentState;//賦值給上一個狀態
            }
            t.Init();//執行初始化
            CurrentState = t;//當前狀態賦值
            CurrentState.ComeEvent(t);//進入狀態
        }

        public void SwitchState(int id)
        {
            if (!StateDt.ContainsKey(id))//判斷當前狀態有沒有註冊
                return;

            State t = StateDt[id];//經過Id找到這個狀態

            if (CurrentState != null)
            {
                if (CurrentState.GetCurrentStateId() == id)
                    return;
                CurrentState.LeaveEvent(t);
                PrevisousState = CurrentState;
            }
            t.Init();//執行初始化
            CurrentState = t;
            CurrentState.ComeEvent(t);

        }

    }

狀態機狀態GameState

public enum GameState
    {
        GAME_CONNECT_STATE,//開始
        GAME_CONNECT_ING,
        GAME_CONNECT_ERROR,
        GAME_CONNECT_END,
    }

GameConnectStart狀態

public class GameConnectStart : State
    {
        public void ComeEvent(State state)
        {
            Console.WriteLine("進入Start狀態");
        }

        public int GetCurrentStateId()
        {
            return (int)GameState.GAME_CONNECT_STATE;
        }

        public void Init()
        {
            Console.WriteLine("Start狀態進行初始化");
        }

        public void LeaveEvent(State state)
        {
            Console.WriteLine("Start狀態結束" +(GameState)state.GetCurrentStateId() + "狀態進來");
        }
    }

GameConnectIng狀態

public class GameConnectIng : State
    {
        public void ComeEvent(State state)
        {
            Console.WriteLine("進入ING狀態");
        }

        public int GetCurrentStateId()
        {
            return (int)GameState.GAME_CONNECT_ING;
        }

        public void Init()
        {
            Console.WriteLine("ING狀態進行初始化");
        }

        public void LeaveEvent(State state)
        {
            Console.WriteLine("ING狀態結束" + (GameState)state.GetCurrentStateId() + "狀態進來");
        }
    }

GameConnectERROR狀態

public class GameConnectERROR : State
    {
        public void ComeEvent(State state)
        {
            Console.WriteLine("進入ERROR狀態   開始切換End狀態");
            SingletonPattern.GetInstace().SwithcStateMachine(GameState.GAME_CONNECT_END);//切換狀態結束
        }

        public int GetCurrentStateId()
        {
            return (int)GameState.GAME_CONNECT_ERROR;
        }

        public void Init()
        {
            Console.WriteLine("ERROR狀態進行初始化,拋出錯誤");
        }

        public void LeaveEvent(State state)
        {
            Console.WriteLine("ERROR狀態結束" + (GameState)state.GetCurrentStateId() + "狀態進來");
        }
    }

GameConnectEnd狀態

public class GameConnectEnd : State
    {
        public void ComeEvent(State state)
        {
            Console.WriteLine("進入END狀態");
        }

        public int GetCurrentStateId()
        {
            return (int)GameState.GAME_CONNECT_END;
        }

        public void Init()
        {
            Console.WriteLine("END狀態進行初始化");
        }

        public void LeaveEvent(State state)
        {
            Console.WriteLine("END狀態結束" + (GameState)state.GetCurrentStateId() + "狀態進來 /n");
        }
    }

建立一個單利來執行這個狀態機 (怎麼執行都行~本身看着方便就行)

SingletonPattern(單利)

public class SingletonPattern
    {
        static SingletonPattern Instance;

        GameStateMachine gameStateMachine = new GameStateMachine();//狀態機

        //四種狀態
        GameConnectStart gameConnectStart = new GameConnectStart();
        GameConnectIng gameConnectIng = new GameConnectIng();
        GameConnectERROR gameConnectERROR = new GameConnectERROR();
        GameConnectEnd gameConnectEnd = new GameConnectEnd();

        //單利
        public static SingletonPattern GetInstace()
        {
            if (Instance == null)
            {
                Instance = new SingletonPattern();
            }
            return Instance;
        }

        /// <summary>
        /// 狀態註冊
        /// </summary>
        public void Init()
        {
            gameStateMachine.Register(gameConnectStart);
            gameStateMachine.Register(gameConnectIng);
            gameStateMachine.Register(gameConnectERROR);
            gameStateMachine.Register(gameConnectEnd);
        }

        /// <summary>
        /// 切換狀態
        /// </summary>
        /// <param name="state"> 狀態類型 </param>
        public void SwithcStateMachine(GameState state)
        {
            gameStateMachine.SwitchState((int)state);
        }
    }

在 主程序中運行

static void Main(string[] args)
        {
            SingletonPattern.GetInstace().Init();//註冊

            SingletonPattern.GetInstace().SwithcStateMachine(0);
            SingletonPattern.GetInstace().SwithcStateMachine((GameState)1);
            SingletonPattern.GetInstace().SwithcStateMachine((GameState)2);

            Console.ReadKey();
        }
相關文章
相關標籤/搜索