游戏AI实现-有限状态机
有限状态机(finite-state machine,FSM)又称有限状态自动机(finite-state automaton,FSA),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。
在状态机中,每个字符占据一个状态。通常,动作或行为与每个状态相关联。因此,只要字符保持在该状态,它将继续执行相同的动作。
状态通过转换连接在一起。每个转换从一个状态指向另一个状态,即目标状态,并且每个转换都有一组相关条件。如果游戏确定转换的条件得到满足,则角色将状态更改为转换的目标状态。当转换的条件得到满足时,它被称为触发,当转换被跟随到新的状态时,它已经被触发。
代码实现:
创建状态机类:
public class StateMachine
{
private State currentState;
public void SwitchState(State newState)
{
currentState?.Exit();
currentState = newState;
currentState?.Enter();
}
private void Update()
{
currentState?.Tick(Time.deltaTime);
}
}
创建一个基础的状态类:
public abstract class State
{
protected StateMachine m_machine;
public State(StateMachine stateMachine)
{
this.m_machine = stateMachine;
}
public abstract void Enter();
public abstract void Tick(float deltaTime);
public abstract void Exit();
}
应用:
模拟一个AI,首先初始化在Idle状态,在饱腹值低于40的时候,开始寻找食物,找到食物之后开始进食,进食完成后转换为idle状态。状态转换如下图:
创建新的状态类:
public class Idle : State
{
Player player;
public Idle(Player player,StateMachine stateMachine) :base(stateMachine){
this.player = player;
}
public override void Enter()
{
}
public override void Exit()
{
}
public override void Tick(float deltaTime)
{
if(player.m_hungryValue < 40)
{
this.m_machine.SwitchState(new Hungry(this.player,this.m_machine));
}
}
}
public class Hungry : State
{
private float timer = 0;
private Player m_player;
public Hungry(Player player,StateMachine stateMachine) : base(stateMachine) {
this.m_player = player;
}
public override void Enter()
{
Debug.Log("我饿了");
}
public override void Exit()
{
Debug.Log("找到食物了");
}
public override void Tick(float deltaTime)
{
this.timer += deltaTime;
if(this.timer > 4)
{
this.m_machine.SwitchState(new Eat(this.m_player, this.m_machine));
this.timer = 0;
}
}
}
public class Eat : State
{
private float timer = 0;
private Player m_player;
public Eat(Player player,StateMachine stateMachine) : base(stateMachine) {
this.m_player = player;
}
public override void Enter()
{
Debug.Log("吃饭了");
}
public override void Exit()
{
Debug.Log("吃饱了");
}
public override void Tick(float deltaTime)
{
this.timer += deltaTime;
if (this.timer > 4)
{
this.m_player.m_hungryValue = 100;
this.m_machine.SwitchState(new Idle(this.m_player, this.m_machine));
this.timer = 0;
}
}
}
创建调用类:
public void InitFSM()
{
this.m_statemchine = new StateMachine();
this.m_statemchine.SwitchState(new Idle(this,m_statemchine));
}
public void Update()
{
this.m_statemchine?.Update();
}
结果:
参考书籍与链接:
《AI FOR GAMES》
Managing enemy state using State Machines in Unity [AI #03] (youtube.com)
Make a Basic Finite State Machine in Unity/C# - For Beginners! (youtube.com)