2024-07-12 Unity AI状态机1 —— 框架介绍

文章目录

  • 1 有限状态机
  • 2 状态机实现框架
    • 2.1 StateMachine
    • 2.2 BaseState
    • 2.3 ...State
    • 2.4 IAIObject
  • 3 框架类图

本文章参考 B 站唐老狮 2023 年直播内容。点击前往唐老狮 B 站主页。

1 有限状态机

​ 有限状态机(Finite - State Machine,FSM),又称有限状态自动机,简称状态机。是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

  • 有限:有限度,不是无限的。

  • 状态:指所拥有的所有状态。

举例说明:

​ 人会做很多个动作,即有很多种状态,包括站立、走路、跑步、攻击、防守、睡觉等等。我们每天都会在这些状态中切换,而且这些状态虽然多但是是有限的。当达到某种条件时,就会在这些状态中进行切换,且这种切换时随时可能发生。

​ 游戏中的怪物 AI 表现一般为巡逻、朝玩家移动、攻击、逃跑、格挡等等状态。即使怪物 AI 表现看起来比较复杂,但是深入观察和分析,它们的状态一般是有限的,只是在不同条件下切换不同状态,由于状态的多样性和美术表现的多样性,让我们觉得它是比较智能的。

​ 因此,“有限”和“行为状态”这两个特点,使得游戏 AI 适用于使用有限状态机实现。

2 状态机实现框架

  1. StateMachine(状态机类,用于统一管理各个状态)。

  2. BaseState(状态基类,抽象出状态的共有内容)。

  3. …State(各状态类,有多少个状态就有几个状态类,均继承状态基类)。

  4. IAIObject(怪物 AI 接口,用于规范所有 AI 的共同行为)。

2.1 StateMachine

​ 有限状态机类,用于管理各个状态之间的切换。同时需要记录所有状态,因此需要如下成员:

  1. StateDictionay:记录所有状态。
  2. NowState:当前处于的状态。
  3. AIObject:附属在哪个 AI 对象上。
  4. AddState():向外部提供添加状态的方法(执行一帧)。
  5. ChangeState():向外部提供切换状态的方法(执行一帧)。
  6. UpdateState():向外部提供更新状态的方法(每帧调用)。

​ 基本结构如下:

using System;
using System.Collections.Generic;

/// <summary>
/// 有限状态机类,用于管理各个状态之间的切换
/// </summary>
public class StateMachine
{
    /// <summary>
    /// 管理所有状态的字典容器
    /// </summary>
    private Dictionary<EAIState, BaseState> _stateDic = new Dictionary<EAIState, BaseState>();

    private BaseState _nowState; // 当前状态
    
    public IAIObject AIObject; // 管理的 AI 对象

    /// <summary>
    /// 初始化方法
    /// </summary>
    /// <param name="aiObject">待管理的 AI 对象</param>
    public void Init(IAIObject aiObject) {
        AIObject = aiObject;
    }

    /// <summary>
    /// 添加 AI 状态
    /// </summary>
    public void AddState(EAIState state) { ... }

    /// <summary>
    /// 切换状态
    /// </summary>
    /// <param name="state"></param>
    public void ChangeState(EAIState state) { ... }

    /// <summary>
    /// 更新当前状态
    /// </summary>
    public void UpdateState() { ... }
}

2.2 BaseState

​ 状态基类负责提取所有状态共有的特性,并声明为抽象类(Abstract),规范每个状态的共同行为。其共有特性基本包括如下:

  1. AIState:状态类型(所有状态需要告诉外面自己是哪种类型)。
  2. StateMachine:附属的状态机。
  3. OnStateEnter():进入状态时执行的逻辑(执行一帧)。
  4. OnStateUpdate():处于该状态时不断更新的逻辑(每帧更新)。
  5. OnStateExist():离开状态时执行的逻辑(执行一帧)。

​ 基本结构如下:

using UnityEngine;

/// <summary>
/// 状态基类
/// </summary>
public abstract class BaseState
{
    public virtual EAIState AIState { get; } // 状态类型

    protected StateMachine _stateMachine; // 附属的状态机

    public BaseState(StateMachine stateMachine) {
        _stateMachine = stateMachine;
    }

    /// <summary>
    /// 进入状态
    /// </summary>
    public abstract void OnStateEnter();

    /// <summary>
    /// 保持状态
    /// </summary>
    public abstract void OnStateUpdate();

    /// <summary>
    /// 离开状态
    /// </summary>
    public abstract void OnStateExit();
}

2.3 …State

​ 在各个具体状态中,可以有独立的数据或逻辑,但每个状态都需要实现由基类规范的共同逻辑。

​ 以 PatrolState(巡逻状态)为例,其基本结构如下:

using System;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;

/// <summary>
/// 巡逻状态类,处理巡逻逻辑
/// </summary>
public class PatrolState : BaseState
{
    // 巡逻数据
    ...

    public override EAIState AIState { get => EAIState.Patrol; } // 表示自己是巡逻状态

    public PatrolState(StateMachine stateMachine) : base(stateMachine) {
        // 初始化
        ...
    }

    public override void OnStateEnter() { ... }  // 进入巡逻状态的逻辑实现

    public override void OnStateUpdate() { ... } // 处于巡逻状态的逻辑实现

    public override void OnStateExit() { ... }   // 退出巡逻状态的逻辑实现

    // 其他逻辑、方法封装等
    ...
}

2.4 IAIObject

​ AI 对象接口,规定 AI 对象必须继承该接口,用于规范 AI 对象的行为。

​ 在 StateMachine 中,不会存储具体的 AI 对象,而是存储 IAIObject,指向对应的 AI 对象。不同的 AI 对象均需要实现 IAIObject 中规范的逻辑,从而使 StateMachine 能够适用于具有不同逻辑的不同 AI 对象。

​ 基本实现如下:

using UnityEngine;

/// <summary>
/// AI 对象接口,用于规范 AI 对象的行为
/// </summary>
public interface IAIObject
{
    public Transform Transform { get; } // AI 对象的 Transform

    public Transform TargetTransform { get; } // 目标监测对象的 Transform

    public float AttackRange { get; } // 攻击范围
    
    public Vector3 BornPos { get; } // 出生位置

    public void Move(Vector3 targetPos); // 移动

    public void StopMove(); // 停止移动

    public void Attack(); // 攻击

    public void ChangeAction(EAction action); // 切换指定动作
    
    // 等等
    ...
}

3 框架类图

StateMachine_AI 框架介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/799635.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux的学习(四):磁盘,进程,定时,软件包的相关命令

简介 关于磁盘管理&#xff0c;进程管理&#xff0c;定时任务&#xff0c;软件包管理的命令的使用 磁盘管理类命令 du du 目录名&#xff1a; 查看文件和目录占用的磁盘空间 参数&#xff1a; -h&#xff1a;可以看到大小的单位&#xff0c;g,mb-a&#xff1a;还可以看到文…

日前光伏功率曲线预测

《利用 2DG&#xff32;A&#xff0d;BiLSTM 模型的日前光伏功率曲线预测方法》 利用2DGRA实现最佳历史相似日数据的获取&#xff0c;根据日功率曲线的波动性将总数据分为3类&#xff08;晴空条件、轻度非晴空条件和重度非晴空条件&#xff09;&#xff0c;根据3种分类&#x…

SpringCloud架构师面试

一、微服务是什么 1、基本概念 微服务是一种架构风格&#xff08;区别于单体架构、垂直架构、分布式架构、SOA架构&#xff09;&#xff0c;应用程序被划分为更小的、流程驱动的服务。 2、微服务的特征 轻量化&#xff1a;将复杂的系统或者服务进行纵向拆分&#xff0c;每个…

【自然语言处理】面向新冠肺炎的社会计算应用

面向新冠肺炎的社会计算应用 1 任务目标 1.1 案例简介 新冠肺炎疫情牵动着我们每一个人的心&#xff0c;在这个案例中&#xff0c;我们将尝试用社会计算的方法对疫情相关的新闻和谣言进行分析&#xff0c;助力疫情信息研究。本次作业为开放性作业&#xff0c;我们提供了疫情…

计算机网络之广域网

广域网特点: 主要提供面向通信的服务&#xff0c;支持用户使用计算机进行远距离的信息交换。 覆盖范围广,通信的距离远&#xff0c;需要考虑的因素增多&#xff0c; 线路的冗余、媒体带宽的利用和差错处理问题。 由电信部门或公司负责组建、管理和维护&#xff0c;并向全社会…

Access denied for user ‘root‘@‘localhost‘ (using password: YES)解决办法

在Spring配置数据源时&#xff0c;当使用Spring容器加载druid.properties数据库连接池配置文件时&#xff0c;容易碰到create connection SQLException, url: jdbc:mysql://127.0.0.1:3306/mydbs, errorCode 1045, state 28000 java.sql.SQLException: Access denied for user …

在JavaScript中,什么是解构赋值(destructuring assignment)?

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介在JavaScript中&#xff0c;什么是解构赋值&#xff08;destructuring assignment&#xff09;&#xff1f;1. 引言2. 解构赋值的概念3. 数组解构赋值3.1 基本语法3.2 跳过元素3.3 默认值3.4 交换变量值 4. 对象解构赋值4.1 基本语…

springboot系列教程(一):简介与入门案例(含源码)

一、SpringBoot简介 SpringBoot继承了Spring优秀的基因&#xff0c;上手难度小简化配置&#xff0c;提供各种默认配置来简化项目配置内嵌式容器简化Web项目&#xff0c;简化编码 Spring Boot 则会帮助开发着快速启动一个 web 容器&#xff0c;在 Spring Boot 中&#xff0c;只…

React学习笔记03-----手动创建和运行

一、项目创建与运行【手动】 react-scripts集成了webpack、bable、提供测试服务器 1.目录结构 public是静态目录&#xff0c;提供可以供外部直接访问的文件&#xff0c;存放不需要webpack打包的文件&#xff0c;比如静态图片、CSS、JS src存放源码 &#xff08;1&#xff09…

QT多线程下,信号槽分别在什么线程中执行,如何控制?

可以通过connect的第五个参数进行控制信号槽执行时所在的线程 connect有几种连接方式&#xff0c;直接连接、队列连接和 自动连接 直接连接&#xff08;Qt::DirectConnection&#xff09;&#xff1a;信号槽在信号发出者所在的线程中执行 队列连接&#xff08;Qt::QueuedConn…

whereis命令是 Linux 和类 Unix 系统中的一个命令行工具,用于定位二进制程序、源代码和手册页(man pages)的位置

文章目录 1、whereis2、实例 1、whereis whereis 命令是 Linux 和类 Unix 系统中的一个命令行工具&#xff0c;用于定位二进制程序、源代码和手册页&#xff08;man pages&#xff09;的位置。当你想要快速找到某个程序或命令的安装位置时&#xff0c;whereis 命令会非常有用。…

关于无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上 解决方法

文章目录 1. ERNEL32.dll 下载2. 解决方法 &#x1f44d; 个人网站:【 洛秋小站】 1. ERNEL32.dll 下载 Windows 7 在安装postman时报错缺少动态链接库,提示缺少.NET Framework,这是因为本地缺少相应的dll文件导致的&#xff0c;这时就需要下载ERNEL32.dll文件&#xff0c;在解…

MySQl高级篇-查询优化篇

SQL性能分析 SQL性能下降原因&#xff1a; 查询语句写的烂索引失效&#xff08;数据变更&#xff09;关联查询太多join&#xff08;设计缺陷或不得已的需求&#xff09;服务器调优及各个参数设置&#xff08;缓冲、线程数等&#xff09; SQL调优过程&#xff1a; 观察&…

【大语言模型】私有化搭建-企业知识库-知识问答系统

下面是我关于大语言模型学习的一点记录 目录 人工智能学习路线 MaxKB 系统(基于大语言模型的知识问答系统) 部署开源大语言模型LLM 1.CPU模式(没有好的GPU&#xff0c;算力和效果较差) 2.GPU模式&#xff08;需要有NVIDIA显卡支持&#xff09; Ollama网络配置 Ollama前…

nodejs安装部署运行vue前端项目

文章目录 1.安装nodejs2.安装Vue CLI1.配置npm镜像源&#xff1a;2.安装Vue CLI&#xff1a;3.创建Vue项目4.启动Vue项目5.Express 1.安装nodejs Node.js 是一个免费、开源、跨平台的 JavaScript 运行时环境&#xff0c;它让开发人员能够创建服务器、Web 应用、命令行工具和脚…

硬件基础学习笔记

关于硬件基础的知识整理 三极管&#xff08;两个PN节组成的器件&#xff09;MOSFET&#xff0c;场效应管&#xff08;Field Effect Transistor&#xff09;1、增强型场效应管符号&#xff1a;2、开关特性&#xff1a; 对于一些硬件知识&#xff0c;容易忘记需要反复记忆&#x…

【杰理蓝牙开发】AC632 开发板烧录实例

AC632 开发板烧录实例 0. 个人简介 && 授权须知1. 硬件板卡介绍2. 代码烧录2.1 使用USB接口烧录2.2 使用串口烧录 3. 为什么要用烧录器供电&#xff1f; 0. 个人简介 && 授权须知 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c…

量化投资基础(一)之Black-Litterman模型

点赞、关注&#xff0c;养成良好习惯 Life is short, U need Python 量化投资基础系列&#xff0c;不断更新中 1. 投资组合收益率与风险 假设市场有 N N N 个资产&#xff0c;其随机收益率分别为 R 1 , R 2 , … , R N R_1,R_2,\dots,R_N R1​,R2​,…,RN​ &#xff0c;对应…

【香橙派 AIpro测评:探索高效图片分类项目实战】

前言 最近入手了一块香橙派 AIpro开发板&#xff0c;在使用中被它的强大深深震撼&#xff0c;有感而发写下这篇文章。 本文旨在深入探讨OrangePi AIpro的各项性能&#xff0c;从硬件配置、软件兼容性到实际应用案例&#xff0c;全方位解析这款设备如何在开源社区中脱颖而出&am…

python中的类

类 类的创建 使用class关键字定义一个新的类 创建实例和使用 修改属性 类的访问权限&#xff08;只有属性和方法有访问权限&#xff09; 概念 种类 公有&#xff08;Public&#xff09;&#xff1a;公有成员可以被类的外部访问。这是默认的权限级别&#xff0c;如果不特别指定…