1. 程式人生 > >有限狀態機的構造和詳細解析

有限狀態機的構造和詳細解析

有限狀態機:
關於有限狀態機的定義是狀態機在狀態發生改變的時候 下一狀態不僅和當前狀態有關 還輸入(在下面我們將的裡面就是當前狀態裡的判斷要轉換的方法裡面所執行的判斷)有關。


在遊戲中 有限狀態機的應用很廣泛,不僅實用於所有的角色,怪物中,甚至UI,場景都可以使用有限狀態機來進行管理;
有限狀態機的設計核心:
有限制狀態機設計的時候最核心的原則就是 單一職責原則 和里氏替換原則【不知道這倆的請自行查詢】
單一職責就是:
每一個狀態都有專門的一個指令碼進行處理他的行為;
里氏替換:
所有具體狀態類(下面的(OneState TwoState))繼承於一個抽象狀態類(FSMState);這樣 不管是用那個狀態例項化的物件,都可以藉助基類進行呼叫其中的方法;

基於以上兩點,這種方式才符合開閉原則【不知道 開閉原則 的請自行查詢】;

首先我們先構建狀態類的基類:FSMState

using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 變換條件 列舉
/// </summary>
public enum Transition
{/// <summary>
/// 空的轉換條件
/// </summary>
    Null=0,
    /// <summary>
    /// 對應第一個轉換條件
    /// </summary>
    One,
    Two
}
public enum StateID
{/// <summary>
/// 空狀態
/// </summary>
    Null = 0,
    /// <summary>
    /// 對應第一個裝換狀態
    /// </summary>
    One,
    Two
}
/// <summary>
/// 狀態機的狀態類 沒一個具體的狀態需要繼承其 並重寫一些函式
/// </summary>
public abstract class FSMState
{
    /// <summary>
    ///狀態的ID 會被每一個子類繼承過去
    /// </summary>
    protected StateID stateID;
    /// <summary>
    /// 獲取狀態ID  屬性
    /// </summary>
    public StateID StateID { get { return stateID; } }
    /// <summary>
    /// 每個條件對應的狀態儲存字典 會被每一個子類繼承過去
    /// </summary>
    protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
    /// <summary>
    /// 狀態所屬的狀態機
    /// </summary>
    protected FSMSystem fSM;
    public FSMState(FSMSystem fsm)
    {
        fSM = fsm;
    }
    /// <summary>
    /// 往狀態機裡新增轉換條件和條件對應的狀態
    /// </summary>
    /// <param name="tr">條件</param>
    /// <param name="ID">狀態ID</param>
    public void AddTransition(Transition tr, StateID ID)
    {
        if (tr == Transition.Null)
        {
            Debug.LogError("轉換條件不能為空:【AddTransition】");
            return;
        }
        if (ID == StateID.Null)
        {
            Debug.LogError("狀態不能為空:【AddTransition】");
            return;
        }
        if (map.ContainsKey(tr))
        {
            Debug.LogError(tr+"已經存在:【AddTransition】");
            return;
        }
        map.Add(tr, ID);
    }
    /// <summary>
    /// 刪除某一狀態轉換
    /// </summary>
    /// <param name="tr"></param>
    public void DeleteTransition(Transition tr)
    {
        if (!map.ContainsKey(tr))
        {
            Debug.LogError("狀態不存在 無法刪除");
            return;
        }
        map.Remove(tr);
    }
    /// <summary>
    /// 通過轉換條件 獲取對應的狀態 多用在獲取要轉換的下一個狀態時
    /// </summary>
    /// <param name="tr"></param>
    /// <returns></returns>
    public StateID GetStateIDByTransition(Transition tr)
    {
        if (!map.ContainsKey(tr))
        {
            Debug.Log("該狀態不存在於狀態機中,");
        }
        return map[tr];
    }
    /// <summary>
    /// 進入狀態的第一針呼叫  多用於 初始化該狀態的一些資訊
    /// </summary>
    public virtual void EnterInto()
    {
    }
    /// <summary>
    /// 狀態離開時呼叫   多用於 用來對該狀態善後
    /// </summary>
    public virtual void Leaving()
    {

    }
    /// <summary>
    /// 該狀態執行的行為 沒幀呼叫
    /// </summary>
    public abstract void Action(GameObject[] obj);
    /// <summary>
    /// 判斷當前狀態是否需要轉換到其他狀態 ,沒幀呼叫
    /// </summary>
    public abstract void Reason(GameObject[] obj);

}
然後建立狀態機類:
using System;
using System.Collections.Generic;
using UnityEngine;

public class FSMSystem
{
    /// <summary>
    /// 儲存當前狀態機的每個ID對應的狀態
    /// </summary>
    private Dictionary<StateID, FSMState> states=new Dictionary<StateID, FSMState>();

    /// <summary>
    /// 當前狀態ID
    /// </summary>
    private StateID currentStateID;
    /// <summary>
    /// 當前狀態
    /// </summary>
    private FSMState currentState;
    /// <summary>
    /// 新增狀態機的狀態
    /// </summary>
    /// <param name="state"></param>
    public void addState(FSMState state)
    {
        if (state == null)
        {
            Debug.LogError("要新增的狀態為空");
            return;
        }
        if (states.ContainsKey(state.StateID))
        {
            Debug.LogError("當前狀態已經存在:" + state.ToString() + ";不能重複新增");
            return;
        }
        //如果當前狀態機沒有正在進行的狀態 則吧這個加入狀態機的狀態設定成當前狀態 當然這裡也可以吧這個放在狀態機的建構函式裡直接構造出來
        if (currentState == null)
        {
            currentStateID = state.StateID;
            currentState = state;
        }
        states.Add(state.StateID, state);
    }
    /// <summary>
    /// 刪除某一ID 一般用不到
    /// </summary>
    /// <param name="id"></param>
    public void DeleteState(StateID id)
    {
        if (id == StateID.Null)
        {
            Debug.LogError("要刪除的狀態不能是空狀態");
            return;
        }
        if (!states.ContainsKey(id))
        {
            Debug.LogError("要刪除的狀態不存在:" + id);
            return;
        }
        states.Remove(id);
    }
    /// <summary>
    /// 執行狀態轉變 在狀態裡 判斷狀態是否需要轉換的時候 需要轉換的時候轉換;
    /// </summary>
    /// <param name="tr"></param>
    public void PerformTransition(Transition tr)
    {
        if (tr == Transition.Null)
        {
            Debug.LogError("不能轉換成空條件");
            return;
        }
        StateID id = currentState.GetStateIDByTransition(tr);
        if (id == StateID.Null)
        {
            Debug.LogError("當前要轉換到的狀態為空狀態");
        }
        if (!states.ContainsKey(id))
        {
            Debug.LogError("當前狀態不存在於狀態機中 無法轉換"+ id);
        }
        //校驗完畢 執行轉換
        //未轉換狀態時 執行狀態離開操作
        currentState.Leaving();
        //更換狀態
        currentState = states[id];
        currentStateID = id;
        //執行狀態進入的操作
        currentState.EnterInto(); 
    }
    /// <summary>
    /// 執行當前狀態的行為方式;
    /// </summary>
    /// <param name="obj">這裡的OBJ是用來判斷轉換條件和行為物件的 可以直接在具體狀態中用欄位儲存 在狀態進入時用進入狀態的函式初始化</param>
    public void Update( GameObject[] obj)
    {
        currentState.Reason(obj);
        currentState.Action(obj);
    }
}

上面就是狀態機的基礎 下面我們來看看怎麼使用:


我們簡單的建立了兩個具體狀態類(我並沒有寫完整 只是大概的寫了下):
using System;
using System.Collections.Generic;
using UnityEngine;


public class OneState : FSMState
{
    /// <summary>
    /// 實現構造方法
    /// </summary>
    /// <param name="fsm"></param>
    public OneState(FSMSystem fsm) : base(fsm)
    {
    }

    public override void Action(GameObject[] obj)
    {
        //這裡寫上這個狀態所需要執行的東西
    }

    public override void Reason(GameObject[] obj)
    {
        //這裡執行這個狀態轉換到其他狀態的判斷
    }
}
第二個具體狀態類:
using System;
using System.Collections.Generic;
using UnityEngine;
public class TwoState : FSMState
{
    /// <summary>
    /// 實現構造方法
    /// </summary>
    /// <param name="fsm"></param>
    public TwoState(FSMSystem fsm) : base(fsm)
    {
    }

    public override void Action(GameObject[] obj)
    {
        //這裡寫上這個狀態所需要執行的東西
    }

    public override void Reason(GameObject[] obj)
    {
        //這裡執行這個狀態轉換到其他狀態的判斷
    }
}
有限狀態機的使用者:
using System;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 這個是使用有限狀態機的 比如玩家 怪物 等等
/// </summary>
public class UseFSM:MonoBehaviour
{
    private FSMSystem fSMSystem;
    private void Awake()
    {
        MakeFSM();
    }
    private void Update()
    {
        fSMSystem.Update(new GameObject[] { });//這裡傳入當前狀態判斷轉換條件是所需要依賴的物件 比如 怪物判斷是否能攻擊時 需要傳入玩家 因為需要藉助玩家計算攻擊距離是否足夠
        //這裡的另一種方式是將判斷所依賴的物件在狀態裡進行獲取 並在該狀態的 EnterInto 方法中初始化;
    }
    void MakeFSM()
    {
        fSMSystem = new FSMSystem();
       //製作狀態並設定該狀態的轉換條件
        FSMState one = new OneState(fSMSystem);
        one.AddTransition(Transition.One, StateID.One);
        FSMState two = new TwoState(fSMSystem);
        two.AddTransition(Transition.Two, StateID.Two);


        //將狀態加入到狀態機中
        fSMSystem.addState(one);
        fSMSystem.addState(two);


    }
}

下面附上原始碼下載地址: 希望大家多多斧正 

原始碼連結:https://pan.baidu.com/s/1mi8A46O  密碼:wf6d

相關推薦

有限狀態構造詳細解析

有限狀態機:關於有限狀態機的定義是狀態機在狀態發生改變的時候 下一狀態不僅和當前狀態有關 還輸入(在下面我們將的裡面就是當前狀態裡的判斷要轉換的方法裡面所執行的判斷)有關。在遊戲中 有限狀態機的應用很廣泛,不僅實用於所有的角色,怪物中,甚至UI,場景都可以使用有限狀態機來進

TCP三次握手、四次端口有限狀態

TCP三次握手、四次端口和有限狀態機1、TCP用三次握手(three-way handshake) 一對終端同時初始化一個它們之間的連接是可能的。但通常是由一端打開一個套接字(socket)然後監聽來自另一方的連接,這就是通常所指的被動打開(passive open)。服務器端被被動打開以後,用戶端就能開始創

文字版 描述TCP三次握手四次揮手以及有限狀態

切換 list 遠方 是什麽 int last 關閉 ive tcp報文 客戶端和服務器 ,雙方都處於第一次交互的情況下展開通信 三次握手 1.首先 服務器 需要是處於listen收聽狀態下才能接受報文客戶端由closed狀態 打開並向服務器發送報文SYN=1 申請建

TCP 握手揮手圖解(有限狀態

一個 tle 客戶端使用 正常的 一點 而不是 情況下 tcp狀態機 流程 1、引言 TCP 這段看過好幾遍,老是記不住,沒辦法找工作涉及到網絡編程這塊,各種問 TCP 。今天好好整理一下握手和揮手過程。獻給跟我一樣忙碌,找工作的童鞋,歡迎大神批評指正。 2、TCP 的

有限狀態在程式設計中作用意義

1.簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。 2.關於狀態機的一個極度確切的描述是它是一個有向圖形,由一組節點和一組相應的轉移函式組成。狀態機通過響應一系列事件而“執行”。每個事件都在屬於“當前” 節點的轉移函式的控制範圍內,其中函式的範

數學之美 系列十 有限狀態地址識別

地址的識別和分析是本地搜尋必不可少的技術,儘管有許多識別和分析地址的方法,最有效的是有限狀態機。一個有限狀態機是一個特殊的有向圖(參見有關圖論的系列),它包括一些狀態(節點)和連線這些狀態的有向弧。下圖是一個識別中國地址的有限狀態機的簡單的例子。 每一個有限狀態機都有一個啟始狀態和一個終止狀態和若干中間狀態

確定有限狀態非確定有限狀態詳解 包含Java實現原始碼(Nondeterministic finite automata)

本文將講解確定有限自動狀態機和非確定有限自動狀態機的特點和區別。將結合圖片例子重點講解什麼是非確定有限自動狀態機。最後講解如何將非確定狀態機轉換為確定的狀態機。多圖預警!! 有限自動狀態機可以分為確定的和不確定的。“確定性”將在下文詳講。“有限”性表示存在一個

獨立項目-角色控制器-有限狀態(FSM)

技術分享 OS pos .com com 過渡 動畫過渡 unity 狀態機   學習內容:     Unity5的新動畫系統       1.動畫導入 分動畫       2.創建動畫狀態機       3.設置動畫過渡 設置動畫跳轉條件       4.動畫重定向 獨立

go - FSM(有限狀態)初體驗

層次 time lba 當前 時機 警告 pen nil 自定義 FSM有限狀態機 /** * @Author: wsp * @Time : 2018/4/11 16:45 * @Description: */ package fsmStrudy import

Verilog筆記.3.有限狀態

情況 || mage 參數 lose default def ril 定義 有限狀態機有限狀態機是由寄存器組和組合邏輯構成的硬件時序電路,其狀態(即由寄存器組的1和0的組合狀態所構成的有限個狀態)只可能在同一時鐘跳變沿的情況下才能從一個狀態轉向另一個狀態,究竟轉向哪一狀態還

FPGA學習筆記(七)——FSM(Finite State Machine,有限狀態)設計

fault mil 系統 time 編碼 代碼 ril esc 寫法   FPGA設計中,最重要的設計思想就是狀態機的設計思想!狀態機的本質就是對具有邏輯順序和時序規律的事件的一種描述方法,它有三個要素:狀態、輸入、輸出:狀態也叫做狀態變量(比如可以用電機的不同轉速作為狀態

從React Redux的實際業務場景來看有限狀態

寫在前面 上一篇:從Promise的實現來看有限狀態機 上一篇講到了一個簡單的,利用了有限狀態機的前端實現Promise。Promise的有限狀態機除了start以及finish兩個狀態,其核心的三個狀態其實就是一個非同步行為的三種狀態:PENDING、FULFILLED、REJECTED。通過非同步行為

前端狀態管理與有限狀態

原文連結 當下前端流行的框架,都是用狀態來描述介面(state => view),可以說前端開發實際上就是在維護各種狀態(state),這已經成為目前前端開發的共識。 View = ViewModel(Model); 複製程式碼 理想情況下,ViewModel 是純函式,給定相同的 Mod

Verilog_有限狀態

名詞解釋 狀態機就是一種能夠描述具有邏輯順序和時序順序事件的方法。 狀態機有兩大類:Mealy型和Moore型。 Moore型狀態機的輸出只與當前狀態有關,而Mealy型狀態機的輸出不僅取決於當前狀態,還受到輸入的直接控制,並且可能與狀態無關。 當使用Veril

C/C++——strcpy函式的 幾種 實現 詳細 解析

C/C++——strcpy函式的實現 和解析 題目:      已知strcpy函式的原型是:         &nb

有限狀態(FSM)的設計

有限狀態機(FSM)的設計_zhangxianhe  有限狀態機(FSM)是一種常見的電路,由時序電路和組合電路組成。  設計有限狀態機的第一步是確定採用Moore 狀態機還是採用Mealy 狀態機。 Mealy 型:狀態的轉變不僅和當前狀態有關,而且跟各輸入訊號有關; Moo

Unity簡單有限狀態實現

【前言】 本篇來說一下關於簡單有限狀態機的演算法實現,當然我們的幾個狀態會比較簡單,而且本身我也是處於入門狀態,所以當成一個簡單的知識積累。有限狀態機,顧名思義,狀態是有限個的,而且狀態之間是關聯的,本篇寫的狀態機,其實是類似寫遊戲裡面的AI機器人,就是那些遊戲

Unity3d 有限狀態

using System.Collections; using System.Collections.Generic; using UnityEngine; //裝換條件 public enum Transition { NullTransition=0, SeePlayer, LostPlaye

有限狀態(FSM)寫法的個人總結(一段式,二段式,三段式)

      狀態機描述時關鍵是要描述清楚幾個狀態機的要素,即如何進行狀態轉移,每個狀態的輸出是什麼,狀態轉移的條件等。具體描述時方法各種各樣,最常見的有三種描述方式:      (1)一段式:整個狀態機寫到一個always模組裡面,在該模組中既描述狀態轉移,又描述狀態的輸入

基於委託與事件的有限狀態設計與實現(Unity3d)

有限狀態機設計與實現 前言 最近看到一句話,就是優秀是一種習慣,所以突然就總想寫點什麼,當作是遊戲開發這條路上的學習筆記吧,另外也時刻提醒自己需要不斷努力。 什麼是狀態機? 先貼百度百科的概念內容吧: 有限狀態機,(英語:Finite-state machine