1. 程式人生 > >Unity中實現一個狀態機

Unity中實現一個狀態機

維基百科:有限狀態機(英語:finite-state machine,縮寫:FSM)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。

本文參照quick-cocos中的StateMachine, 實現了Unity版本的有限狀態機。

實現思路:

  1. 建立一個狀態機物件
public class StateMachine : MonoBehaviour {
    ...
}
  1. 初始化狀態機資訊,包括事件和回撥函式。
// 事件
public class SMEvent
{
    readonly string name;
    readonly
List<string> froms; readonly string to; public string Name { get { return name; } } public List<string> Froms { get { return froms; } } public string To { get { return to; } } public SMEvent(string _name, List<string> _froms, string _to) { name = _name; froms = _froms; to = _to; } } // 回撥函式
Dictionary<string, Func<SMEvent, bool>> _callbacks;
  1. 切換狀態通過執行事件實現。
public int DoEvent(string name){ ... }
  1. 執行事件的條件判斷
public bool IsReady(){...} :返回狀態機是否就緒
public string GetState(){...} :返回當前狀態
public bool IsState(string state){...} :判斷當前狀態是否是引數state狀態
public bool CanDoEvent(string eventName){...
}:當前狀態如果能完成eventName對應的event的狀態轉換,則返回true public bool CanNotDoEvent(string eventName){...} :當前狀態如果不能完成eventName對應的event的狀態轉換,則返回true public bool IsFinishedState(){...}:當前狀態如果是最終狀態,則返回true
  1. 執行回撥函式

// 在事件EVENT開始前被啟用
private bool BeforeThisEvent(SMEvent smEvent) {...}


// 在離開舊狀態STATE時被啟用
private bool LeaveThisEvent(SMEvent smEvent) {...}


// 在進入新狀態STATE時被啟用
private bool EnterThisEvent(SMEvent smEvent) {...}


// 在事件EVENT結束後被啟用
private bool AfterThisEvent(SMEvent smEvent) {...}


// 在任何事件開始前被啟用
private bool BeforeAnyEvent(SMEvent smEvent) {...}

// 在任何事件結束後被啟用
private bool AfterAnyEvent(SMEvent smEvent) {...}

// 在進入任何狀態時被啟用
private bool EnterAnyState(SMEvent smEvent) {...}


// 在離開任何狀態時被啟用
private bool LeaveAnyState(SMEvent smEvent) {...}

// 當狀態發生改變的時候被啟用
private bool ChangeAnyState(SMEvent smEvent) {...}

使用示例:

// 建立一個狀態機例項
StateMachine fsm = gameObject.AddComponent<StateMachine>();

// 新增事件和狀態
List<SMEvent> events = new List<SMEvent>();
events.Add(new SMEvent("move", new List<string> { "idle", "jump"}, "walk"));
events.Add(new SMEvent("attack", new List<string> { "idle", "walk" }, "jump"));
events.Add(new SMEvent("normal", new List<string> { "walk", "jump"}, "idle"));
events.Add(new SMEvent("lie", new List<string> { "move", "idle"}, "falldown"));

// 添加回調函式
Func<SMEvent, bool> onenteridle = x => Walk(x);
Func<SMEvent, bool> onenterwalk = x => Jump(x);
Func<SMEvent, bool> onenterjump = x => Idle(x);
Func<SMEvent, bool> onenterlie = x => FallDown(x);

Dictionary<string, Func<SMEvent, bool>> callbacks = new Dictionary<string, Func<SMEvent, bool>>();
callbacks.Add("onenternormal", onenteridle);
callbacks.Add("onentermove", onenterwalk);
callbacks.Add("onenterattack", onenterjump);
callbacks.Add("onenterlie", onenterlie);

// 初始化狀態機
string initial = "idle";
fsm.SetupState(events, callbacks, initial, "", false);;

// 回撥
private bool Walk(SMEvent smEvent) {
    Debug.LogError("Walk");
    return true;
}

private bool Jump(SMEvent smEvent)
{
    Debug.LogError("Jump");
    return true;
}

private bool Idle(SMEvent smEvent)
{
    Debug.LogError("Idle");
    return true;
}

private bool FallDown(SMEvent smEvent)
{
    Debug.LogError("FallDown");
    return true;
}

例項地址:

其它:

  1. 狀態和事件名可以通過配置表或者列舉來實現
  2. Walk,Jump等具體的實現可以通過狀態模式, 移動指標地址實現。

如有錯誤,歡迎指出。

email:dxmdxm1992#gmail.com

相關推薦

Unity實現一個狀態

維基百科:有限狀態機(英語:finite-state machine,縮寫:FSM)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。 本文參照quick

unity實現一個類似x光掃描效果

先來看下效果:原理很簡單,首先獲取頂點到攝像機的觀察方向,然後與頂點的法線方向進行點積算出投影的長度最後再乘以我們設定的顏色值即為最終要輸出的顏色。這裡要注意觀察方向與法線方向要進行歸一化。shader程式碼:Shader "Custom/XLight" { Propert

unity實現一個光照越強透明度越高的shader

可能描述的不清楚,先看下效果: 就是這樣,被燈光照亮的部分,會變透明,而且越亮透明度越高。 這裡主要就是通過計算當先位置的法線在燈光方向上的投影大小,投影越大則亮度越高, 因為透明度為0-1,所這裡我們把(1-亮度)作為透明度即可。 完整的shader程式碼: Shad

Unity實現FSM有限狀態

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

Unity協程解析——狀態實現的程式碼分步執行

Unity協程的效果 協程是一個分部執行,遇到條件(yield return 語句)會掛起,直到條件滿足才會被喚醒繼續執行後面的程式碼。 Unity在每一幀(Frame)都會去處理物件上的協程。Unity主要是在Update後去處理協程(檢查協程的條件是否滿足) 協程跟Upd

Linux實現一個簡單的進度條【轉】

做的 會有 發現 文件 rsquo 實時 時間 改進 常見 轉自:http://blog.csdn.net/yuehailin/article/details/53999288 說起進度條,其實大家常常見到,比如說你在下載視頻或文件的時候,提示你當前下載進度的就是我們今天

unity一個圖片切割成兩個UI圖片

unity3 mode png 鼠標 eight 圖片效果 height pri unity 1、在unity3D的Project視圖下選中需要更改的圖片,將圖片的Texture Type更改為Sprite (2D and UI),點擊Apply即可。操作如圖所示:

unity實現三個Logo圖片進行3秒鐘的若隱若現後互相切換Logo圖片

date += srp val logs ima 精靈 texture 透明 private List<Sprite> storeTexture; public void Start() { storeTextu

關於Unity實現繩索物理效果 Obi - Advanced Rope Simulation插件解析

阻尼 旋轉 eval mil 抖動 amp ola all 動作 Obi - Advanced Rope Simulation 繩索插件學習文檔 插件分享: 鏈接:https://pan.baidu.com/s/1eTwZOrg 密碼:p8wa //插件導入有錯誤產生,將

使用C語言實現一個虛擬

doesn 寄存器 php 浪費 vid c11 machine 指向 編程語言 使用C語言實現一個虛擬機 2015-6-22 21:32| 發布者: joejoe0332| 查看: 2891| 評論: 0|原作者: leoxu, Serval, 社會主義好, los

Unite 2018 | 《崩壞3》:在Unity實現高品質的卡通渲染

width diffuse 動態生成 LG 編輯 www. tgs term 謝謝 本篇文章為Unity官方論壇發布的文章 由於全是幹貨,為了方便自己查找,也為了避免刪除找不到了 於是復制了過來。。。 原文地址: http://forum.china.unity3d.c

如何在react實現一個table切換?

PE AR tst === name tab abc 直接 his 廢話不說,直接貼代碼,供新手參考 export default class TabComponent extends Component { constructor(props){ super(prop

在Android實現一個簡易的Http服務器

.get json data ESS public 瀏覽器 顯示 getmethod blank 最近遇到一個需求需要在App中創建一個Http服務器供供瀏覽器調用,用了下開源的微型Htpp服務器框架:NanoHttpd,項目地址:https://github.com/Na

(9) tomcat實現同一虛擬所有應用程序單點登錄SSO

所有應用 單點登錄 分享圖片 png 技術 應用 單點 登錄 技術分享 (9) tomcat中實現同一虛擬機中所有應用程序單點登錄SSO

C#或unity實現正弦函式

C#或unity中實現正弦函式 本類用於第一,需要繪製一條正弦曲線的朋友;第二,需要根據正弦曲線控制物體運動的朋友;裡面都有註釋,程式碼如下: unity中使用的程式碼: public class Curvy_Sin { /// <summary> /// 週期

Unity實現控制物體以自定義的速度沿Y軸旋轉90度(也可自定義度數)後停止,然後返回原來位置

1、需要控制沿Y軸旋轉的物體,如下所示: 2、編寫控制該物體旋轉的指令碼,如下所示:  using UnityEngine; using System.Collections; public class Test_CycleRoate : MonoBehaviour {

定義棧的資料結構,請在該型別實現一個能夠得到棧所含最小元素的min函式(時間複雜度應為O(1))。

import java.util.Stack; public class Solution { private Stack<Integer> min_stack=new Stack<Integer>(); private Stack<Integer&

unity實現簡單的程式紋理 10.3.1

using UnityEngine; using System.Collections; using System.Collections.Generic; //在unity中實現簡單的程式紋理 10.3.1 //在編輯模式執行 [ExecuteInEditMo

定義棧的資料結構,請在該型別實現一個能夠得到棧所含最小元素的min函式(時間複雜度應為O(1))

/** 思路:利用兩個棧來實現,一個主棧正常壓棧出棧,一個輔助棧用來儲存主棧所有值的最小值, 壓棧時,當壓入的值比輔助棧棧頂值大時,主棧正常壓棧,輔助棧不壓棧,小於等於二者都壓棧; 出棧時,當主棧和輔助棧棧頂元素不相等時,主棧正常出棧,輔助棧不出棧。 */ class Sol

Java祕術:用列舉構建一個狀態

原文連結   作者: 綜述 Java中的enum比其他的語言中的都強大,這產生了很多令人驚訝的用法。本文中,我將列出Java中的enum的一些特性,然後將這些特性應用到一起構成一個狀態機。 Enum的單例和工具類用法 你可以非常簡單地用一個enum構建一個單例或者工具類。 </pre&