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

news2024/9/21 20:47:08

文章目录

  • 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.coloradmin.cn/o/1921843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何让招投标数据成为企业决策的金钥匙?

在当今数据驱动的时代&#xff0c;招投标信息作为行业竞争情报的重要组成部分&#xff0c;正日益成为企业制定战略决策的关键依据。本文将深入探讨招投标数据采集的重要性&#xff0c;以及它如何为企业决策提供强有力的数据支持&#xff0c;同时揭秘如何高效、精准地获取这些数…

花几千上万学习Java,真没必要!(二)

1、注释&#xff1a; java代码注释分3种&#xff1a; 单行注释&#xff1a;//注释信息 多行注释: /*注释信息*/ 文本注释:/**注释信息*/ public class TestComments {// 这是单行注释&#xff0c;用于注释单行代码或解释代码功能/* 这是多行注释&#xff0c;用于注释多行代码…

eMMC规范 - 寻址/信息寄存器/总线协议/时序图/速度模式

存储器寻址 e•MMC 规范的早期实现&#xff08;至 v4.1 的版本&#xff09;是采用 32-bit 域实现字节寻址的。这种寻址 机制允许最大 2 GB 的 e•MMC 容量。 为了支持更大的容量&#xff0c;寻址机制升级到支持扇区寻址&#xff08; 512B 扇区&#xff09;。对所有容量大于 2 …

在PyQt中为自己开发的软件实现远程文件“一机一码”授权管理实例

在使用PyQt搞软件开发时&#xff0c;开发者往往想要给自己的软件添加一个授权机制&#xff0c;只有当客户提供了授权码并且开发者将授权码放在授权管理系统的时候&#xff0c;客户端才能正常启动。这几天小陶就在捣鼓这个事&#xff0c;发现确实是可行的。 如果没有进行授权&a…

mybatis动态传入参数 pgsql 日期 Interval ,day,minute

mybatis动态传入参数 pgsql 日期 Interval 在navicat中&#xff0c;标准写法 SELECT * FROM test WHERE time > (NOW() - INTERVAL 5 day)在mybatis中&#xff0c;错误写法 SELECT * FROM test WHERE time > (NOW() - INTERVAL#{numbers,jdbcTypeINTEGER} day)报错内…

html5——CSS高级选择器

目录 属性选择器 E[att^"value"] E[att$"http"] E[att*"http"] 关系选择器 子代&#xff1a; 相邻兄弟&#xff1a; 普通兄弟&#xff1a; 结构伪类选择器 链接伪类选择器 伪元素选择器 CSS的继承与层叠 CSS的继承性 CSS的层叠性 …

redis介绍与布署

redis remote dictionary server&#xff08;远程字典服务器&#xff09; 是一个开源的&#xff0c;使用c语言编写的非关系型数据库&#xff0c;支持内存运行并持久化&#xff0c;采用key-value的存储形式。 单进程模型意味着可以在一台服务器上启动多个redis进程&#xff0c;…

基于语义的法律问答系统

第一步&#xff0c;准备数据集 第二步&#xff0c;构建索引数据集&#xff0c;问答对数据集&#xff0c;训练数据集&#xff0c;召回评估数据集 第三步&#xff0c;构建dataloader,选择优化器训练模型&#xff0c;之后召回评估 第四步&#xff0c;模型动转静&#xff0c;之后…

改摄像头IQ(目前我知道的功能是看色彩)

1、SrcCode\Dx\580_CARDV_ETHCAM_RX_EVB&#xff08;每个项目不同找到对应的&#xff09;\isp.dtsi 将下面路径改成对应镜头的 2、将新的IQ复制到文件夹下code\hdal\vendor\isp\configs\dtsi

Vue3 引入腾讯地图 包含标注简易操作

1. 引入腾讯地图API JavaScript API | 腾讯位置服务 (qq.com) 首先在官网注册账号 并正确获取并配置key后 找到合适的引入方式 本文不涉及版本操作和附加库 据体引入参数参考如下图 具体以链接中官方参数为准标题 在项目根目录 index.html 中 写入如下代码 <!-- 引入腾…

【SQL】如何用SQL写透视表

【背景】 报表中有一大需求是透视表,目前有很多分析类应用也搭载了此类功能,那么我们能不能直接用SQL做透视表呢? 【分析】 BI类软件将透视表功能做在了前端,但是数据本身还是存储在数据库中,所以必然有方法可以用SQL直接实现透视表。 【心法】 透视表是任意选取一个…

【C语言】经典C语言笔试面试题目

01. 请填写bool , float, 指针变量 与“零值”比较的if语句。 提示&#xff1a;这里“零值”可以是0, 0.0 , FALSE 或者“空指针”。 例如 int n 与“零值”比较的 if 语句为&#xff1a; if ( n 0 ) if ( n ! 0 )以此类推。 请写出 bool flag 与“零值”比较的 if 语句&a…

IT运维也有自己的节日 724向日葵IT运维节,三大版本如何选?

“724运维节”&#xff0c;是2016年由开放运维联盟发起倡议&#xff0c;广大运维人员共同投票产生的属于运维人自己的节日。 对于运维人最大的印象&#xff0c;那就是工作都需要7x24小时待命&#xff0c;是名副其实的“日不落骑士”&#xff0c;这也是大家选择724这一天作为运…

2024最新6月泛二级域名秒收泛目录(二级域名泛站群)

5月免费版本无后台 无更新功能不自动引蜘蛛 2024年5月最新泛程序&#xff0c;秒收秒排&#xff01;&#xff08;泛型程序&#xff09; - 虚良SEO博客 新曾功能&#xff1a; 后台管理 蜘蛛统计 域名添加 一键强引蜘蛛 蜘蛛统计 识别真假蜘蛛 全自动引蜘蛛 域名要求 …

viteExternalsPlugin 插件管理外部依赖

viteExternalsPlugin 是一个 Vite 插件&#xff0c;用于将指定的模块或库配置为外部依赖 安装&#xff1a; npm i vite-plugin-externals 1.实战用途 比如从项目 index.html 中引入一些SDK文件&#xff0c;我这个是引入的CHATUI vite.config.js 配置&#xff1a; import {…

OSS存储桶密钥泄露【案例】

OSS存储桶密钥泄露 同样的&#xff0c;在前几天的攻防演练中的经历&#xff0c;本文我们将为OSS存储桶单独做文章 公开配置文件泄露 录屏、截图缺失了。发现这个存储桶密钥是因为我在鹰图对一个能够控制生成类似容器的站点&#xff0c;抓包发现api是另一个子域的站点&#x…

C#变量、常量与运算符

文章目录 变量变量定义命名规则作用域和生命周期 常量特殊字符常量 运算符算术运算符关系运算符逻辑运算符位运算符赋值运算符其他运算符 变量 变量就是一个存储空间的名字&#xff0c;变量是什么类型&#xff0c;这个空间里面存储的就是什么类型的数据。 变量定义 <data_t…

C语言学习记录day3

第三天主要是练习代码编写 一、有序数组元素的查找 顺序法时间复杂度O(n) 二分法时间复杂度O&#xff08;log2n&#xff09; 二、演示多个字符从两端向中间移动汇聚 三、模拟登录密码场景 四、求最大公因数 五、... 剩余更多代码练习已上传至个人github&#xff08;日期1…

SSM学习6:Spring事务

简介 事务作用&#xff1a;在数据层保障一系列的数据库操作同成功同失败Spring事务作用&#xff1a;在数据层或业务层保障一系列的数据库操作同成功同失败 public interface PlatformTransactionManager{void commit(TransactionStatus status) throws TransactionStatus ;vo…

C++第五弹 -- 类与对象(中下) (赋值运算符重载函数 const成员函数 取地址操作符重载函数)

目录 前言一. 赋值运算符重载1. 运算符重载2. 赋值运算符的重载3. 前置 和 后置 重载 二. 日期类的实现三. const成员函数四. 取地址及const取地址操作符重载总结 前言 本文将深入探讨C中的运算符重载&#xff0c;重点讲解赋值运算符、前置/后置运算符、取地址运算符的重载方法…