1、有限状态机的定义

定义:一个有限状态机是一个设备,或是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使得从一个状态变换到另一个状态,或者是促使一个输出或者一种行为的发生。一个有限状态机在任何瞬间只能处在一种状态。

举个例子:

灯的开关是一个非常简单的有限状态机。他有两种状态:开或关。状态之间的变换是通过你手指的输入产生的。向上按开关,产生从关到开的状态变换,向下按开关,产生从开到关的状态变换。

Java 有限状态机的写法 有限状态机程序_Java 有限状态机的写法

2、有限状态机的实现

方法1、switch/if

以灯的开关为例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum StateType
{
    LightOn,
    LightOff
}
public class FSMTest : MonoBehaviour
{
    private StateType _state;

    private bool switchDir;//开关方向 false为向下,true为向上,通过你的输入可以改变这个值
    // Start is called before the first frame update
    void Start()
    {
        _state = StateType.LightOff;
        switchDir = false;
    }

    // Update is called once per frame
    void Update()
    {
        UpdateState(_state);
    }

    void UpdateState(StateType state)
    {
        switch (state)
        {
            //关灯状态
            case StateType.LightOff:
                if (switchDir)
                {                    
                    state = StateType.LightOn;
                    //...一些别的操作
                }
                break;
            //开灯状态
            case StateType.LightOn:
                if (!switchDir)
                {
                    state = StateType.LightOff;
                    //...一些别的操作
                }
                break;
        }
    }
}

上述方法在遇到状态较复杂,或者状态的拓展较频繁时,代码会变得非常难懂,拓展状态也并不灵活

方法2、状态变换表

一个例子:

当前状态

条件

状态转换

逃跑

安全

巡逻

攻击

比敌人弱

逃跑

巡逻

受到威胁并比敌人强

攻击

巡逻

受到威胁并比敌人弱

逃跑

表中的每个状态可以抽象为一个对象或者是一个函数,这个表会被智能体在规则的时间间隔内询问,这样做的话,状态的结构会更加的条理清晰,增加新的状态模块也会更加方便一些

方法3、内置的规则

例子:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class State  
{
    public virtual void Execute(Player player)
    {

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Runaway : State
{
    public override void Execute(Player player)
    {
        if (player.isSafe)
        {
            player.ChangeState(new Sleep());
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sleep : State
{
    public override void Execute(Player player)
    {
        if (player.isThreatened)
        {
            player.ChangeState(new Runaway());
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    private State curState;

    public bool isSafe;//判断是否处于安全状态
    public bool isThreatened;//判断是否处于受威胁状态

    // Update is called once per frame
    void Update()
    {
        if(curState != null)
        {
            curState.Execute(this);
        }
    }
    
    public void ChangeState(State newState)
    {
        curState = newState;
    }
}

state作为状态类的一个基类,拥有一个虚函数供子类重写,每当有一个新的状态,就继承state类,并重写Execute方法。player类里面执行的状态完全由curState的值来决定,这样的话,状态本身进行了封装并且在内部给出了影响状态变换的规则。

这个结构被称为状态设计模式,它提供了一种优雅的方式来实现状态驱动行为。它非常容易为每种状态增加进入状态和退出状态的动作,你只需要为每个状态创建Enter和Exit方法并相应的调整智能体的ChangeState方法即可。