1. 程式人生 > >FSM有限狀態機學習及Unity3D案例講解

FSM有限狀態機學習及Unity3D案例講解

引言:近日忙於畢業論文,今天看到漲了3個粉絲,不甚驚喜。遂今日更新FSM有限狀態機學習,希望大家共同進步!

開發版本:Unity 2017.1.1f1、VS 2017

適合人群:初學Unity者

一.有限狀態機定義

有限狀態機(英文:Finite State Machine,簡稱FSM),是指在不同階段呈現不同的執行狀態的系統,這些狀態是有限的,不重疊的。這樣的系統在某一時刻一定會處於其中所有狀態中的一個狀態,此時它接收一部分的輸入,產生相應的響應,並且遷移到可能的狀態。

    一般有限狀態機有一下幾種型別的動作:
    1.進入動作:進入當前狀態時執行

    2.退出動作:退出當前狀態時執行

    3.輸入動作:在當前狀態時執行
    4.轉移動作:在進行特定切換狀態時執行

    有限狀態機提供了描述和控制應用邏輯的強大方法,可以應用於控制NPC行為,圖形介面管理等方面。FSM可以使得各個狀態之間相互獨立,互不影響,避免了狀態與狀態之間的耦合度,具有規則簡單,可讀性和可驗證性等優點。

二.整理思路

簡單的有限狀態機就是switch語句,但如果狀態過多的情況下,switch會使得程式碼顯得臃腫,可擴充套件性很低。

假設敵人有四種狀態,Idle、Patrol、Chase、Attack,switch實現方法如下:

public enum States
{
    Idle,//空閒狀態
    Patrol,//巡邏狀態
    Chase,//追逐狀態
    Attack//攻擊狀態
}

public class SimpleFSM : MonoBehaviour
{
    private States currentState = States.Idle;

    private void Update()
    {
        switch (currentState)
        {
            case States.Idle:
                //TODO 空閒狀態動作
                break;
            case States.Patrol:
                //TODO 巡邏狀態動作
                break;
            case States.Chase:
                //TODO 追逐狀態動作
                break;
            case States.Attack:
                //TODO 攻擊狀態動作
                break;
        }
    }
}

接下來整理“高階的”有限狀態機實現方法,FSM由狀態類和管理類組成,先建立一個狀態基類FSMState,用於實現狀態類的基本方法,每新增一種狀態,就作為它的子類。然後,用一個管理類FSMSystem把所有狀態管理起來,方便使用狀態機。FSM類圖如下所示:

三.實現程式碼

1.定義列舉型別

public enum StateID
{
    NullStateID,
}
public enum Transition
{
    NullTransition
}

定義每一種狀態的ID和狀態之間的轉換條件

2.FSMState基類

public abstract class FSMState
{
    protected StateID stateID;
    public StateID ID { get { return this.stateID; } }
    protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
    protected FSMSystem fsm;

    public FSMState(FSMSystem fsm)
    {
        this.fsm = fsm;
    }

    /// <summary>
    /// 新增轉換條件
    /// </summary>
    /// <param name="trans">轉換條件</param>
    /// <param name="stateID">轉換的目標狀態</param>
    public void AddTransition(Transition trans, StateID stateID)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError(trans + "為空,轉換條件不允許為空");return;
        }
        if (stateID == StateID.NullStateID)
        {
            Debug.LogError(stateID + "為空,狀態ID不允許為空"); return;
        }
        if (map.ContainsKey(trans))
        {
            Debug.LogError(trans + "已經存在,請檢視該轉換條件是否正確");
        }
        else
        {
            map.Add(trans, stateID);
        }
    }

    /// <summary>
    /// 刪除轉換條件
    /// </summary>
    /// <param name="trans">需刪除的轉換條件</param>
    public void DeleteTransition(Transition trans)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError(trans + "為空,轉換條件不允許為空"); return;
        }
        if (map.ContainsKey(trans) == false)
        {
            Debug.LogError(trans + "不存在,請檢視該轉換條件是否正確"); 
        }
        else
        {
            map.Remove(trans);
        }
    }

    /// <summary>
    /// 通過轉換條件,得到目標狀態
    /// </summary>
    /// <param name="trans">轉換條件</param>
    /// <returns>返回目標狀態</returns>
    public StateID GetTargetStateID(Transition trans)  
    {
        if (map.ContainsKey(trans) == false)
        {
            Debug.LogError(trans + "不存在,請檢視該轉換條件是否正確");
            return StateID.NullStateID;
        }
        else
        {
            return map[trans];
        }
    }

    public virtual void DoBeforeEntering() { }//進入動作
    public virtual void DoAfterLeaving() { }//離開動作
    public abstract void Act();//輸入動作
    public abstract void Reason();//轉移動作
}

狀態類主要儲存轉換條件和轉換狀態的字典,可以新增刪除轉換條件,根據條件返回對應的狀態,並定義狀態類的四種動作。

3.FSMSystem管理類

public class FSMSystem
{
    private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
    private FSMState currentState;

    /// <summary>
    /// 更新當前狀態行為
    /// </summary>
    public void UpdateFSM()
    {
        currentState.Act();
        currentState.Reason();
    }

    /// <summary>
    /// 新增狀態
    /// </summary>
    /// <param name="state">需管理的狀態</param>
    public void AddState(FSMState state)
    {
        if (state == null)
        {
            Debug.LogError(state + "為空"); return;
        }
        if (currentState == null)
        {
            currentState = state;
        }
        if (states.ContainsValue(state))
        {
            Debug.LogError(state + "已經存在");
        }
        else
        {
            states.Add(state.ID, state);
        }
    }

    /// <summary>
    /// 刪除狀態
    /// </summary>
    /// <param name="id">需要刪除狀態的ID</param>
    /// /// <returns>刪除成功返回true,否則返回false</returns>
    public bool DeleteState(StateID id)
    {
        if (id == StateID.NullStateID)
        {
            Debug.LogError(id + "為空");
            return false;
        }
        if (states.ContainsKey(id) == false)
        {
            Debug.LogError(id + "不存在");
            return false;
        }
        else
        {
            states.Remove(id);
            return true;
        }
    }

    /// <summary>
    /// 執行轉換
    /// </summary>
    /// <param name="trans">轉換條件</param>
    public void PerformTransition(Transition trans)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError(trans + "為空");return;
        }
        StateID targetID = currentState.GetTargetStateID(trans);
        if (states.ContainsKey(targetID) == false)
        {
            Debug.LogError(targetID + "不存在");return;
        }
        FSMState targetState = states[targetID];
        currentState.DoAfterLeaving();
        targetState.DoBeforeEntering();
        currentState = targetState;
    }
}

FSMSystem用來管理各個狀態,字典儲存ID和對應的狀態,可以新增刪除狀態,並執行狀態轉換。

四.案例講解

假設敵人按照路線巡邏,當發現玩家的時候,開始追逐。但玩家跑出追擊範圍的時候,敵人繼續回去巡邏。

專案的原始檔在文末,有需要的童鞋可以自行下載。

敵人巡邏效果如下:

敵人發現玩家開始追逐,當玩家逃離後,返回繼續巡邏,效果如下:

分析此時敵人狀態有兩種,巡邏和追逐,轉換條件也對應有兩種

public enum StateID
{
    NullStateID,
    PatrolState,
    ChaseState
}
public enum Transition
{
    NullTransition,
    FindPlayer,
    LosePlayer
}

建立兩個子類PatrolState和ChaseState都繼承自FSMState,分別用來實現巡邏和追逐的狀態行為。

在Enemy類中,例項化FSMSystem物件,新增巡邏和追逐狀態,還有之間的轉換條件

public class Enemy : MonoBehaviour
{
    private FSMSystem fsm;

    private void Start()
    {
        fsm = new FSMSystem();
        FSMState patrolState = new PatrolState(fsm);
        FSMState chaseState = new ChaseState(fsm);
        fsm.AddState(patrolState);
        fsm.AddState(chaseState);
        patrolState.AddTransition(Transition.FindPlayer, StateID.ChaseState);
        chaseState.AddTransition(Transition.LosePlayer, StateID.PatrolState);
    }

    private void Update()
    {
        fsm.UpdateFSM();
    }
}

FSM有限狀態機除了實現敵人的行為外,還可以用來管理UI介面的切換,使用方式基本相似。如果大神發現我分享的學習記錄中有錯誤,還請不吝賜教。

案例百度雲連結:連結:https://pan.baidu.com/s/1XYhmn3i9kwskai8_MEtAvg 密碼:jchj

覺得我分享的學習記錄不錯的,點贊關注我哦!

相關推薦

FSM有限狀態學習Unity3D案例講解

引言:近日忙於畢業論文,今天看到漲了3個粉絲,不甚驚喜。遂今日更新FSM有限狀態機學習,希望大家共同進步! 開發版本:Unity 2017.1.1f1、VS 2017 適合人群:初學Unity者 一.有限狀態機定義 有限狀態機(英文:Finite State Mach

FSM有限狀態學習

using System.Collections; using System.Collections.Generic; using UnityEngine; public class FSMSystem { public FSMState currentState; private Dict

學習筆記(三) 簡單的狀態模式&FSM有限狀態框架的實現(二)

之前釋出的那篇部落格可能說的並是不非常清楚,所以整理了一下,也參考了一些文件,於是又寫了一篇總結。 一、有限狀態機FSM的要點 1、擁有一組狀態,並且可以再這組狀態之間進行切換。 2、狀態機同時只能存在一個狀態,英雄不能能同時處於跳躍和站立。而防止這一點就是使用

FSM有限狀態

1、什麼是有限狀態機 有限狀態機(Finite State Machine),簡稱FSM,它由一組有限個狀態、輸入和根據輸入及現有狀態轉換為下一個狀態的轉換函式組成,當然,通常每個狀態機都必須有一個初始狀態。它有兩個重要的概念:狀態和轉移。有限狀態機在很多領域都有運用,這裡介紹的是在unity遊戲開發中

Unity--FSM有限狀態

有限狀態機,先理解是幹什麼的,有限表示這個是有限度的不是無限的,狀態,指的是所擁有的所有狀態,這麼來理解,人有情緒,比如說生氣,無感,喜悅,難過,生氣,幸福等,那麼這些情緒是固有的幾種,是所謂有限,那麼那些情緒就是不同的狀態,人可以在這些狀態之中進行轉換,此時是開心的,下一

在Unity中實現FSM有限狀態

簡介 有限狀態機,(英語:Finite-state machine, FSM),又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型 -- 引用百度百科的解釋: 有限狀態機(FSM)是遊戲AI的一種常用模型,我做一個簡單的

FSM有限狀態架構

      首先我們應該定義一個狀態基類FSMBase,裡面有一些動畫狀態的基本行為,比如動畫狀態的進入,持續,離開等,然後因為人物並不是只有一個狀態,所以我們應該建立一個狀態管理器來管理狀態,裡面應該定義一些方法,比如我們應該定義一些狀態的共同邏輯,比如對狀態進行儲存,新增

Unity3D有限狀態FSM學習筆記【7】使用例項

using UnityEngine; using System.Collections; public class TestUIState : MonoBehaviour { public static EventSystem.Dispatcher Events = new EventSystem.Di

Unity3D有限狀態FSM學習筆記【3】FSState類

本系列筆記轉載自遊戲蠻牛專欄作家Jackel的論壇文章,詳細介紹了FSM的建立與使用,特與眾分享。連結:http://www.manew.com/thread-37136-1-1.html 該類主要是狀態的基本操作及事件的新增與觸發。程式碼如下: using System;

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

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

關於FSM有限狀態)的學習2

以下內容參照《unity3d 人工智慧程式設計》--Aung Sithu Kyaw,Clifford Peters ,Thet Naing Swe編著</span> 最近在研究此書,花費幾天時間,略有收穫,所以寫下此編文章,計劃是3章,這是第一章,受個人能力限

獨立項目-角色控制器-有限狀態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

有限狀態FSM)的設計

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

Unity3d 有限狀態

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

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

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

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

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

有限狀態FSM)讀書筆記

有限狀態機(Finite-state machine)又稱有限狀態自動機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。 有限狀態機FSM的實現 1.用而(開關/箱)或(如果/其他)實現簡單粗暴,適合簡單的小型狀態機; 2.用設計模式中的state pattern,把複

基於有限狀態Unity3D中實現的簡單搓招系統

在諸如街霸、拳皇等格鬥遊戲中,搓招指的是玩家通過在短時間內連續輸入特定的指令來釋放角色的招式(比如右下右拳釋放升龍拳) 那麼如何通過狀態機來實現搓招呢? 我們可以讓每個招式都持有一個狀態機,把這個招式要求的輸入指令作為狀態機的狀態而存在。依然以升龍拳為例,我們可以

Unity3d實現有限狀態系統

在之前有過介紹一個視覺化有限狀態機編輯器外掛PlayerMaker在這裡也可以在我們的程式碼中實現一個狀態機首先建立一個指令碼,來管理我們的各個狀態using System.Collections; using System.Collections.Generic; usin