0%

FSM有限状态机

简介

了解FSM之前需要了解一下状态机

FSM是状态机的一种实现方式,它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上判断事件,变连续处理为离散数字。

原理

发生事件(event)后,根据当前状态(cur_state) ,决定执行的动作(action),并设置下一个状态号(nxt_state)。

特点

  • 有限
  • 状态离散性

因为有限状态机是个封闭系统,具有结束状态,所以它是有限的。

状态离散性:离散的某一时刻只能处于某种状态之下,且需要满足某种条件才能从一种状态转移到另一种状态。

设计

状态机的设计状态之间的关系是一个麻烦的事情,所以在设计的过程中需要借助状态图或者状态表来设计。

个人喜欢现态/次态表,其中填写事件和动作,然后将条件梳理。

代码

FSM实现事件检测可以通过“轮询”或者“事件驱动”的方式。下面代码是采用轮询的方式。

这是一本书中提到的通用FSM状态机源码 其中包括了1.Description 2.Component 3.C#-FSMSystem.cs 4.Example。

部分代码展示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public enum Transition
{
NullTransition = 0,
}
public enum StateID
{
NullStateID = 0,
}
public abstract class FSMState
{
protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
protected StateID stateID;
public StateID ID { get { return stateID; } }

public void AddTransition(Transition trans, StateID id){}
public void DeleteTransition(Transition trans){}
public StateID GetOutputState(Transition trans){}

public virtual void DoBeforeEntering() { }
public virtual void DoBeforeLeaving() { }

public abstract void Reason(GameObject player, GameObject npc);
public abstract void Act(GameObject player, GameObject npc);
}

public class FSMSystem
{
private List<FSMState> states;
private StateID currentStateID;
public StateID CurrentStateID { get { return currentStateID; } }
private FSMState currentState;
public FSMState CurrentState { get { return currentState; } }
public FSMSystem()
{
states = new List<FSMState>();
}

public void AddState(FSMState s){}
public void DeleteState(StateID id){}
public void PerformTransition(Transition trans){}
}

点击并拖拽以移动

优缺点

  • 优点
  • 缺点

优点:相对简单的状态机来使用swich那样不方便扩展,将事件放置具体状态中相对来说好维护

缺点:1.随着状态的增加我们会发现有很多相似的状态 2.随着状态的增多,维护链接成本还是很高的 3.很难做到状态并行

下图是我画的状态图

它的表现效果是双方士兵们出阵然后开始群殴,直至一方士兵全部死亡。当时并没有采用现态/次态表,很遗憾很乱,而且事件条件很乱很有可以会出错。如果这时候策划来说,我感觉一方敌人全部死亡之后,呆呆的站在那里很难受,让他们庆祝一下吧。这时候我很方便的添加一个庆祝状态,庆祝之后站立。

它状态少的时候还好,状态多的时候就很尴尬,维护起来的成本很高。而且无法达到并行的目的。而且出阵和冲锋其实有点相似的。状态机的确满足了我的项目需求,但是不可否认的是FSM本身存在的问题,不过相比BT(行为树)自顶向下的轮询方式,它起码可以采用事件驱动的方式来实现状态切换,而且在针对简单的项目需求还是蛮有效的,所以在游戏开发中需要根据具体情况去合理的在状态机和BT之间权衡。然后采用适合自己的项目的方式实现,如下面的扩展。

扩展

  • 分层状态机
  • 并行状态机
  • BT行为树
  • 神经网络