当前位置: 首页 > article >正文

游戏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)


http://www.kler.cn/a/429695.html

相关文章:

  • Android 对接口的封装使用
  • 计算机网络速成
  • 计算机视觉算法实战——步态识别(主页有源码)
  • lerna使用指南
  • 嵌入式系统中的 OpenCV 与 OpenGLES 协同应用
  • 计算机网络 (39)TCP的运输连接管理
  • 通过Zynq FPGA对雷龙SD NAND进行测试
  • 黑马商城docker部署部分MySQL拉取超时解决方法
  • 前端学习纪要
  • java八股-流量封控系统
  • Leetcode 每日一题 1.两数之和
  • Linux图形化工具推荐
  • 【sgUploadImage】自定义组件:基于elementUI的el-upload封装的上传图片、相片组件,适用于上传缩略图、文章封面
  • 【Linux】08 -- 重定向命令及管道命令
  • mac下flutter开发环境的配置
  • CGAL自相交修复测试
  • 使用Python3 连接操作 OceanBase数据库
  • 碰撞算法8 --直线与圆的碰撞
  • UART+DDR3+HDMI联合图像存储与显示系统
  • git 过滤检出包含windows平台不兼容文件
  • FSC认证是什么?FSC认证费用
  • Elasticsearch一分钟
  • 如何借助 LLM Gateway (LLM网关)同时接入多款 AI 大模型?
  • 2024年深圳杯数学建模C题编译器版本的识别问题解题全过程文档及程序
  • C语言 字符数组/多维数组/函数/作用域
  • 【MySQL 进阶之路】存储引擎和SQL优化技巧分析