FSM——Unity中一个简易的有限状态机的实现

2023-11-12

前言:

有限状态机是一种在实现敌人Ai上比较常用的方法,一个最基本的有限状态机可以由三部分组成:
1.状态基类
2.状态类
3.载体类(敌人类、玩家类等等)

一、首先是状态基类的实现:

载体用玩家类来举例,基类中需要实现的主要方法有:
1、进入状态时的函数,在进入状态时调用一次,在这个函数中,我们需要传入一个载体类的引用,以便后续对载体进行操作
2、退出状态时的函数,在退出状态时调用一次
3、状态转换的函数,判断切换状态的条件,满足条件时切换到对应的状态
4、状态执行函数,在这里使用了两个函数来分别执行Updata和FixedUpdata中的逻辑

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

public abstract class StateBase
{
    public Player player;

    /// <summary>
    /// 进入状态时执行的函数
    /// </summary>
    /// <param name="player"></param>
    public virtual void OnEnter(Player player) => this.player = player;

    /// <summary>
    /// 状态在Update中执行的函数
    /// </summary>
    public abstract void OnUpdate();
    
    /// <summary>
    /// 状态在FixedUpdate中执行的函数
    /// </summary>
    public abstract void OnFixedUpdate();


    /// <summary>
    /// 状态退出时执行的函数
    /// </summary>
    public abstract void OnExit();

    /// <summary>
    /// 状态转换条件
    /// </summary>
    public abstract void QuitReason();
}

二、实现了状态基类后,就可以根据需求实现继承了状态基类的状态类了

这里以Idle状态举例

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

public class IdleState : StateBase
{
    public override void OnEnter(Player player)
    {
        base.OnEnter(player);
    }
    public override void OnExit()
    {
       
    }

    public override void OnFixedUpdate()
    {
        
    }

    public override void OnUpdate()
    {
        
    }

    public override void QuitReason()
    {
        
    }
}

三、载体类

这里以Player举例
1.首先我们声明一些需要使用到的状态,并在Awake中实例化它们。
2.之后我们在Updata和FixedUpdata中分别执行我们当前状态的状态执行函数OnUpdata和OnFixedUpdata。
3.我们还需要在Updata中每帧检测是否满足了切换到下一个状态的条件,如果满足了就应该立刻切换到下一个状态,所以我们需要在Updata中执行当前状态的QuiteReason函数
4.我们也可以写一个SwitchState函数来统一的管理我们的状态切换,在每次切换状态时,都需要执行一次当前状态的退出函数OnExit和下一个状态的进入函数OnEnter

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

public class Player : MonoBehaviour
{
    private StateBase currentState;
    private StateBase idleState;
    private StateBase walkState;
    private void Awake()
    {
        idleState = new IdleState();
        walkState = new WalkState();
        //初始化状态
        SwitchState(stateEnums.IdleState);
    }
    void Start()
    {
        
    }

    void Update()
    {
        currentState?.QuitReason();
        currentState?.OnUpdate();
    }

    private void FixedUpdate()
    {
        currentState?.OnFixedUpdate();
    }


    void SwitchState(stateEnums state)
    {
        currentState?.OnExit();
        currentState = state switch
        {
            stateEnums.IdleState => idleState,
            stateEnums.WalkState => walkState,
            _ => null,
        };
        currentState?.OnEnter(this);
    }
}

public enum stateEnums
{
    IdleState,WalkState
}

这样我们就实现了一个最基本的有限状态机。

关于优化的一些思考

  1. 我们目前对各种状态的实例化处理还只是直接在脚本中声明一个状态变量并实例化,但如果状态非常多时,一个一个的声明变量就会显得代码很冗长,这时我们可以在SwitchState中考虑结合反射,来通过反射直接实例化指定类名的状态类,并将所有声明的状态都统一存储在一个字典中,通过键名来一一对应。
  2. 我们可以考虑将状态机的切换操作,实例化操作等等只针对状态机本身的操作都剥离出来,放在一个单独的FSM静态类中,这样可以让程序进一步的解耦,并提高程序的通用性。

具体代码有空再更啦~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FSM——Unity中一个简易的有限状态机的实现 的相关文章

随机推荐

  • 面试官问我MySQL索引失效怎么排查?懵逼了。。。

    前 言 上一期 我们讲解了sql优化的一般流程 不管是优化join语句 where语句 聚合函数还是排序操作 核心在于利用索引来优化sql语句 但是 大家以为我们为字段创建了索引之后 索引就一定会生效吗 当然不是的 因为索引可能会失效 那索
  • TensorFlow框架做深度学习之命令行参数操作

    想必在linux系统上做开发的小伙伴们对命令行这种东西是熟悉的不能再熟悉了 linux系统时时刻刻都要通过命令行实现各种操作 但是作为资深的windows用户 我是不太习惯用cmd命令控制台去操作应用的 回到今天的主题 为了使我们用Tens
  • Xamarin.Android DatePickerFragment 日期控件

    MainActivity 代码 public class MainActivity Activity TextView dateDisplay Button dateSelectButton protected override void
  • 服务器显示ipv4有两个ip地址,服务器显示ipv4有两个ip地址

    服务器显示ipv4有两个ip地址 内容精选 换一换 查询子网 您可以在API Explorer中直接运行调试该接口 GET v1 project id subnets subnet id 参数说明请参见表1 参数说明名称是否必选说明proj
  • CLI 发行uni-app到微信小程序,如何不打开微信开发者工具去进行小程序发布?

    前言 小程 赶紧把这个UI这里改一下 改完赶紧推个版本 等着测试 哎小程 这个需求客户需要这样改一下 你赶紧改一下推个版本客户等着看 上面这段话相信做开发的同僚或多或少每天都在听 可是小程序的版本发布流程并不像华为云 阿里云等其他云服务器
  • cuda warp内原语——vote instructions&warp instructions

    warp内原语 shfl sync shfl up sync shfl down sync and shfl xor sync 可在warp级别交换线程的变量 写在开头 shfl shfl up shfl down and shfl xor
  • Excel VLOOKUP 初学者教程:通过示例学习

    目录 前言 一 VLOOKUP的用法 二 应用VLOOKUP的步骤 三 VLOOKUP用于近似匹配 四 在同一个表里放置不同的VLOOKUP函数 结论 前言 Vlookup V 代表 垂直 是 excel 中的内置函数 允许在 excel
  • vue监听浏览器窗口的变化,随着窗口变化调整里面table的宽高

    1 在data中设置 1 tableHeight 500 2 screenHeight window innerHeight 2 在mounted中设置 mounted const that this window onresize gt
  • 路由追踪tracert命令

    路由追踪tracert命令Tracert 跟踪路由 是路由跟踪实用程序 用于确定 IP 数据报访问目标所采取的路径 Tracert 命令用 IP 生存时间 TTL 字段和 ICMP 错误消息来确定从一个主机到网络上其他主机的路由 这点和pi
  • springboot整合redis使用介绍

    文章目录 系列文章目录 Springboot集成Netty Springboot集成Rabbitmq Springboot集成Retry springboot集成websocket Springboot集成Redis springboot整
  • Flink_02_算子(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识 内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 Flink程序的组成结构 Source 数据输入 Transform
  • C语言自定义类型一网打尽(结构体、位段/位域、枚举、联合体)

    前言 C语言自定义类型有 结构体 枚举 联合体 内置类型有 int char long double short float等 结构体 struct 结构体声明 结构体 描述一个学生 名字 年龄 电话 性别 定义 下面s1 s3为结构体全局
  • java程序设计成长史项目实战练习

    关于java程序设计实战项目JAVA与Mysql的连接 使用模块化进行连接 下面为具体的代码 为20rg同学项目练习提供参考 还请多多关注 1 二 主程序模块 2 public static void main process throws
  • java中,如何将一个字节数组转换成字符串?

    String tmpStr 我的测试 byte tb tmpStr getBytes String m new String tb System out println m m byte a a b c d 6 String e new S
  • C++编写的一个图书管理系统

    C 编写的一个图书管理系统 2018大一的课设 搬到这纪念一下 共1200多行代码 为图书管理人员编写一个图书管理系统 图书管理系统的设计主要是实现对图书的管理和相关操作 包括3个表 图书信息表 存储图书的基本信息 包括书号 书名 作者 出
  • android content file,Android开发中content://与file://真实文件路径的转换

    问题 最近在开发文件查看器中出现一个问题 接收到一个uri content media external images media 2283 获取到的getPath external images media 2283 打开文件是出现异常
  • 使用Python,OpenCV进行对象追踪

    这篇博客将介绍如何使用Python OpenCV的内置对象跟踪器进行对象跟踪 单目标追踪 并将简单介绍OpenCV库中内置的八种对象跟踪算法 截至OpenCV 3 4 包括 CSRT KCF Boosting MIL TLD MedianF
  • unittest中用ddt将参数传输进测试用例中

    unittest中用ddt传入参数时 传入的参数有几个元素 用例就会执行几次 下面是一个简单的演示 可以复制后直接运行 import numpy as np import unittest import ddt ddt ddt 使用了ddt
  • windows10 修改java环境变量不生效

    一 问题 以前安装过安装版的jdk后 配置过环境变量 然后现在更换jdk版本且修改环境变量并不能生效 如原本安装了1 8 现更换为1 7 且配置了环境变量 但是java version仍显示1 8 二 原因 当使用安装版本的JDK程序时 会
  • FSM——Unity中一个简易的有限状态机的实现

    前言 有限状态机是一种在实现敌人Ai上比较常用的方法 一个最基本的有限状态机可以由三部分组成 1 状态基类 2 状态类 3 载体类 敌人类 玩家类等等 一 首先是状态基类的实现 载体用玩家类来举例 基类中需要实现的主要方法有 1 进入状态时