什麼是FSM狀態機
總的來說,有限狀態機系統,是指不同的階段呈現出不同的運行狀態系統,這些狀態是有限的,不重疊,這樣的系統在某一時刻一定會處於其所有狀態中的一個狀態,此時他接受一部分允許的輸入,產生一部分可能的響應,並且遷移到一部分可能的狀態。
五大要素
- 狀態
- 事件
- 條件
- 動作
- 遷移
遊戲運用
案例演示
說明:Enemy 是遊戲中的一個敵人腳本類,持有FSMSystem(狀態管理類),通過改變敵人的狀態(FSMState)來實現敵人在不同狀態市因執行什麼樣的操作。 StateID (狀態ID),Transiton (狀態類型)。
功能
敵人在三個點之間巡邏(巡邏狀態),當主角靠近時,敵人切換到跟隨狀態,(跟隨狀態),當主角離遠時,敵人切換到巡邏狀態。
FSMState 狀態父級類
定義狀態父級類,之後的每個狀態子類都繼承於FSMState類。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Transiton
{
NullTransiton = 0,
SeePlayer = 1,
LostPlayer = 2,
}
public enum StateID //狀態id
{
NullStateID = 0,
patrol = 1,
Chase = 2,
}
/// <summary>
/// 狀態機框架
/// </summary>
public abstract class FSMState
{
protected StateID stateID;
public StateID ID { get { return stateID; } }
protected Dictionary<Transiton, StateID> map = new Dictionary<Transiton, StateID>();
protected FSMSystem fsm;
public FSMState(FSMSystem _fsm)
{
fsm = _fsm;
}
//添加轉換條件
public void AddTransition(Transiton trans, StateID id)
{
if (trans == Transiton.NullTransiton)
{
Debug.LogError("..................");
return;
}
if (id == StateID.NullStateID)
{
Debug.LogError("=================");
return;
}
map[trans] = id;
}
public void DeleteTransition(Transiton trans)
{
if (trans == Transiton.NullTransiton)
{
return;
}
if (map.ContainsKey(trans) == false)
{
return;
}
map.Remove(trans);
}
/// <summary>
/// 獲取狀態
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public StateID GetQutputState(Transiton trans)
{
if (map.ContainsKey(trans))
{
return map[trans];
}
return StateID.NullStateID;
}
//狀態的生命週期
public virtual void DobeforEntering() { } //進入狀態
public virtual void DoAfterLeaving() { } //倆開狀態
public abstract void Act(GameObject npc); //當前狀態要做的事情
public abstract void Reason(GameObject npc); //判斷轉換條件
}
FSMSystem 狀態管理類
FSMSystem持有FSMState對象,通過管理FSMState對象進行狀態的切換,達到控制敵人在什麼情況執行什麼樣的狀態。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 狀態機框架 管理類
/// </summary>
public class FSMSystem
{
private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
//當前狀態
private StateID currentStateID;
private FSMState currentState; //狀態對象
public void Update(GameObject go)
{
currentState.Act(go);
currentState.Reason(go);
}
//狀態添加
public void AddSatte(FSMState state)
{
if (state == null)
{
return;
}
if (currentState == null)
{
currentState = state;
currentStateID = state.ID;
}
if (states.ContainsKey(state.ID))
{
return;
}
states.Add(state.ID, state);
}
public void DeleteSatte(StateID id)
{
if (id == StateID.NullStateID)
{
return;
}
if (states.ContainsKey(id))
{
return;
}
states.Remove(id);
}
//狀態切換
public void PerformTransition(Transiton trans)
{
if (trans == Transiton.NullTransiton)
{
return;
}
StateID id = currentState.GetQutputState(trans); //判斷是否需要轉換
if (id == StateID.NullStateID)
{
return;
}
//可以轉換
if (states.ContainsKey(id) == false)
{
//不存在
return;
}
FSMState state = states[id];
currentState.DoAfterLeaving();
currentState = state;
currentStateID = id;
currentState.DobeforEntering();
}
}