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

2024-07-13 Unity AI状态机2 —— 项目介绍

文章目录

  • 1 项目介绍
  • 2 模块介绍
    • 2.1 BaseState
    • 2.2 ...State
      • 2.2.1 PatrolState
      • 2.2.2 ChaseState / AttackState / BackState
    • 2.3 StateMachine
    • 2.4 Monster
  • 3 其他功能
  • 4 类图

项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。

1 项目介绍

​ 本项目使用 Unity 2022.3.32f1c1,实现基本的 AI 框架。其中,用 Cube(绿色)代替怪物模型,Cube(红色)代替玩家,即 AI 目标。

image-20240713164018099

​ 项目地址:https://github.com/zheliku/StateMachine_AI。

2 模块介绍

2.1 BaseState

​ 在框架介绍的基础上,添加了两个方法:

  1. DistanceOfXZ(Vector3, Vector3)

    用于计算 xz 平面上的距离(不考虑 y 轴方向)。

  2. DrawGizmos()

    用于辅助绘制范围,在 Scene 窗口中显示。

using UnityEngine;/// <summary>
/// 状态基类
/// </summary>
public abstract class BaseState
{public virtual EAIState AIState { get; } // 状态类型protected StateMachine _stateMachine; // 附属的状态机public BaseState(StateMachine stateMachine) {_stateMachine = stateMachine;}public abstract void OnStateEnter();public abstract void OnStateUpdate();public abstract void OnStateExit();/// <summary>/// 辅助绘制范围,不强制重写/// </summary>public virtual void DrawGizmos() { }/// <summary>/// XZ 平面上的距离/// </summary>protected float DistanceOfXZ(Vector3 pos1, Vector3 pos2) {pos1.y = pos2.y = 0;return Vector3.Distance(pos1, pos2);}
}

2.2 …State

​ 项目实现了 4 种 AI 状态,包括

  • PatrolState(巡逻状态)
  • ChaseState(追逐状态)
  • AttackState(攻击状态)
  • BackState(返回状态)

2.2.1 PatrolState

​ PatrolState 实现较为详细,其将巡逻方式分为 3 种:

public enum EPatrolType
{Stay,       // 原地播放某个动作(睡觉、放哨等)CircleMove, // 圆形范围内随机移动PathMove    // 按照路径移动
}

​ 巡逻数据可以直接在 PatrolState 类中声明。本项目选择封装在 PatrolStateData 中。所有 Data 均继承 ScripteObject 类,可以在 Project 窗口中右键直接创建并配置对应数据。

  • PatrolStateData:所有巡逻种类的共有数据。

  • PatrolStateStayData:原地巡逻的数据。

  • PatrolStateMoveData:移动巡逻的数据。

  • PatrolStateCircleMoveData:圆形范围移动巡逻的数据。

  • PatrolStatePathMoveData:路径移动巡逻的数据。

StateMachine_AI PatrolStateData
  1. Stay:

    原地播放某个动作,因此需要 AI 动作枚举。目前只添加 Sleep 动作。

    public enum EAction
    {Sleep,
    }
    
  2. Move:

    范围内随机移动,分为两种:Circle、Path。区别是获取下一次目标位置的方式不同,因此提取出如下逻辑:

    public class PatrolState : BaseState
    {private PatrolStateData _data; // 巡逻数据.../// <summary>/// 移动/// </summary>private void OnMoveUpdate(IAIObject aiObject, EPatrolType moveType) {var data = (PatrolStateMoveData)_data; // 转化数据..._data.targetPos = moveType switch {EPatrolType.CircleMove => CalCircleTargetPos((PatrolStateCircleMoveData)data),EPatrolType.PathMove   => CalPathTargetPos((PatrolStatePathMoveData)data),_                      => throw new ArgumentOutOfRangeException(nameof(moveType), moveType, null)};...}/// <summary>/// 更新圆形范围目标位置/// </summary>private Vector3 CalCircleTargetPos(PatrolStateCircleMoveData data) { ... }/// <summary>/// 更新路径范围目标位置/// </summary>private Vector3 CalPathTargetPos(PatrolStatePathMoveData data) { ... }...
    }
    

2.2.2 ChaseState / AttackState / BackState

​ 该 3 个状态都遵循以下大致框架:

using UnityEngine;public class ...State : BaseState
{private ...StateData _data;public override EAIState AIState { get => ...; }public AttackState(StateMachine stateMachine) : base(stateMachine) {// 加载数据var data = Resources.Load<...StateData>("StateData/.../...StateData");_data = Object.Instantiate(data);}public override void OnStateEnter() { ... }public override void OnStateUpdate() { ... }public override void OnStateExit() { ... }...
}

2.3 StateMachine

​ AddState()、ChangeState() 和 UpdateState() 逻辑如下:

/// <summary>
/// 添加 AI 状态
/// </summary>
public void AddState(EAIState state) {switch (state) {case EAIState.Patrol:_stateDic.Add(state, new PatrolState(this));break;case EAIState.Back:_stateDic.Add(state, new BackState(this));break;case EAIState.Chase:_stateDic.Add(state, new ChaseState(this));break;case EAIState.Attack:_stateDic.Add(state, new AttackState(this));break;default: throw new ArgumentOutOfRangeException(nameof(state), state, null);}
}/// <summary>
/// 切换状态
/// </summary>
/// <param name="state"></param>
public void ChangeState(EAIState state) {_nowState?.OnStateExit(); // 退出状态if (_stateDic.TryGetValue(state, out BaseState nowState)) { // 进入状态_nowState = nowState;_nowState.OnStateEnter();}
}/// <summary>
/// 更新当前状态
/// </summary>
public void UpdateState() {_nowState?.OnStateUpdate();_nowState?.DrawGizmos(); // 辅助绘图
}

2.4 Monster

​ 怪物类实现了 IAIObject 接口(详见 2024-07-12 Unity AI状态机1 —— 框架介绍),通过 Unity 导航系统中的 NavMeshAgent 实现基本移动。除了 IAIObject 接口,还包含一些自己的数据。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;public class Monster : MonoBehaviour, IAIObject
{public Transform  targetTransform; // 目标位置public GameObject bullet;          // 子弹public float      attackRange = 3; // 攻击范围private Quaternion _startRotation;  // 记录开始攻击时的角度private Quaternion _targetRotation; // 记录目标角度private float      _rotateTime;     // 旋转计时private NavMeshAgent _navMeshAgent; // 导航代理private StateMachine _aiMachine; // AI 状态机private void Start() {_navMeshAgent = GetComponent<NavMeshAgent>();BornPos       = transform.position;_aiMachine = new StateMachine();_aiMachine.Init(this);// 为 AI 添加巡逻状态_aiMachine.AddState(EAIState.Patrol);_aiMachine.AddState(EAIState.Chase);_aiMachine.AddState(EAIState.Attack);_aiMachine.AddState(EAIState.Back);// 更改初始状态_aiMachine.ChangeState(EAIState.Patrol);}private void Update() {_aiMachine.UpdateState();}#region IAIObject 接口实现...#endregion
}

3 其他功能

​ 为了辅助绘图,为 BaseState 添加了 DrawGizmos() 方法(virtual),子类可以实现该方法,在 Scene 窗口中绘制辅助线。同时,在 BaseState 中添加 DistanceOfXZ() 方法,以便所有状态都可使用。以下是 BaseState 的全部逻辑:

using UnityEngine;/// <summary>
/// 状态基类
/// </summary>
public abstract class BaseState
{public virtual EAIState AIState { get; } // 状态类型protected StateMachine _stateMachine; // 附属的状态机public BaseState(StateMachine stateMachine) {_stateMachine = stateMachine;}public abstract void OnStateEnter();public abstract void OnStateUpdate();public abstract void OnStateExit();/// <summary>/// 辅助绘制范围,不强制重写/// </summary>public virtual void DrawGizmos() { }/// <summary>/// XZ 平面上的距离/// </summary>protected float DistanceOfXZ(Vector3 pos1, Vector3 pos2) { ... }
}

​ 辅助绘图时,使用 Unity Asset Store 中的插件 DrawXXL 实现,例如 ChaseState 中的 DrawGizmos 如下:

public override void DrawGizmos() {var aiObject = _stateMachine.AIObject;// 绘制攻击范围DrawShapes.Circle(aiObject.Transform.position, aiObject.AttackRange, Color.red,Vector3.up, lineWidth: 0.05f);// 绘制脱离范围DrawShapes.Circle(aiObject.Transform.position, _data.chaseDistance, new Color(1, 0.5f, 0),Vector3.up, lineWidth: 0.05f, outlineStyle: DrawBasics.LineStyle.dotted);
}

4 类图

StateMachine_AI 部分类图

相关文章:

2024-07-13 Unity AI状态机2 —— 项目介绍

文章目录 1 项目介绍2 模块介绍2.1 BaseState2.2 ...State2.2.1 PatrolState2.2.2 ChaseState / AttackState / BackState 2.3 StateMachine2.4 Monster 3 其他功能4 类图 项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。 1 项目介绍 ​ 本项目使用 Unity 2…...

shell脚本-linux如何在脚本中远程到一台linux机器并执行命令

需求&#xff1a;我们需要从11.0.1.17远程到11.0.1.16上执行命令 实现&#xff1a; 1.让11.0.1.17 可以免密登录到11.0.1.16 [rootlocalhost ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created d…...

Spring Data Redis + Redis数据缓存学习笔记

文章目录 1 Redis 入门1.1 简介1.2 Redis服务启动与停止&#xff08;Windows&#xff09;1.2.1 服务启动命令1.2.2 客户端连接命令1.2.3 修改Redis配置文件1.2.4 Redis客户端图形工具 2. Redis数据类型2.1 五种常用数据类型介绍 3. Redis常用命令3.1 字符串操作命令3.2 哈希操作…...

在项目中,如何使用springboot+vue+springsecurity+redis缓存+Axios+MySQL数据库+mybatis

要在项目中使用springbootvuespringsecurityredis缓存AxiosMySQL数据库mybatis&#xff0c;可以按照以下步骤进行操作&#xff1a; 创建一个Spring Boot项目&#xff0c;并添加所需的依赖。在pom.xml文件中添加Spring Boot、Spring Security、Redis、MySQL和MyBatis的依赖项。 …...

微调 Florence-2 - 微软的尖端视觉语言模型

Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力&#xff0c;因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。 Florence 开箱即用支持多种类型的任务&#xff0c;包括: 看图说话、目标检测、OCR 等等。虽然覆盖面…...

【数据结构】二叉树全攻略,从实现到应用详解

​ &#x1f48e;所属专栏&#xff1a;数据结构与算法学习 &#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ ​ &#x1f341;1. 树形结构的介绍 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做…...

微信小程序加载动画文件

最近在做微信小程序的动画&#xff0c;调研了几种方案 PAG 腾讯自家的&#xff0c;分为完整版和lite版&#xff0c;对于矢量动画挺好的&#xff0c;但是位图会有问题 完整版会逐渐卡死&#xff0c;lite虽然不会卡死&#xff0c;但是很模糊&#xff0c;优点是动画文件很的很小。…...

[计算机网络] VPN技术

VPN技术 1. 概述 虚拟专用网络&#xff08;VPN&#xff09;技术利用互联网服务提供商&#xff08;ISP&#xff09;和网络服务提供商&#xff08;NSP&#xff09;的网络基础设备&#xff0c;在公用网络中建立专用的数据通信通道。VPN的主要优点包括节约成本和提供安全保障。 优…...

SQL 中的 EXISTS 子句:探究其用途与应用

目录 EXISTS 子句简介语法 EXISTS 与 NOT EXISTSEXISTS 子句的工作原理实际应用场景场景一&#xff1a;筛选存在关联数据的记录场景二&#xff1a;优化查询性能 EXISTS 与其他 SQL 结构的比较EXISTS vs. JOINEXISTS vs. IN 多重 EXISTS 条件在 UPDATE 语句中使用 EXISTS常见问题…...

OpenSearch分析WAF日志

Web应用防火墙(WAF)是保护web应用程序的重要工具,而分析WAF日志可以帮助我们更好地了解安全威胁并优化防护策略。本文将介绍15个使用OpenSearch分析WAF日志的实用例子,涵盖基础统计、安全分析、性能监控等多个方面。 准备工作 在开始之前,请确保: WAF日志已经被发送到OpenSea…...

【前端】零基础学会编写CSS

一、什么是CSS CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种是一种用来为结构化文档&#xff08;如 HTML 文档&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&#xff0c;能够对网页中元素位置的排版进行像素级别的精…...

Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战

Day07-ES集群加密&#xff0c;kibana的RBAC实战&#xff0c;zookeeper集群搭建&#xff0c;zookeeper基本管理及kafka单点部署实战 0、昨日内容回顾:1、基于nginx的反向代理控制访问kibana2、配置ES集群TSL认证:3、配置kibana连接ES集群4、配置filebeat连接ES集群5、配置logsta…...

RK3568 V1.4.0 SDK,USB OTG端子不能被电脑识别出adb设备,解决

修改后的/usr/bin/usbdevice: #!/bin/sh # # Usage: # usbdevice [start|update|stop] # # Hookable stages: # usb_<pre|post>_<init|prepare|start|stop|restart>_hook # <usb function>_<pre|post>_<prepare|start|stop>_hook # # Example …...

如何在 Ubuntu 14.04 服务器上使用 Nginx 安装和保护 phpMyAdmin

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 像 MySQL 这样的关系型数据库管理系统在许多网站和应用程序中都是必不可少的。然而&#xff0c;并非所有用户都习惯通过命令行来管…...

redis存入hash,key=>value和key=>(key=>value)使用Python举例

在 Redis 中&#xff0c;HASH 数据结构&#xff08;也称为 HMAP 或 Hash Map&#xff09;允许你存储键值对集合&#xff0c;其中每个键值对都是字段&#xff08;field&#xff09;和值&#xff08;value&#xff09;的映射。在 Python 中&#xff0c;你可以使用 redis-py 库来与…...

Guava LocalCache源码分析:LocalCache的get、put、expand、refresh、remove、clear、cleanUp

Guava LocalCache源码分析&#xff1a;LocalCache的get、put、expand 前言一、get二、put三、expand 前言 上篇文章&#xff0c;详细描写了Guava LocalCache怎样如ConcurrentHashMap对缓存数据进行了分段存储。本章主要针对LocalCache重要的几个接口进行说明。 一、get CanIg…...

linux-arm ubuntu18.04 qmqtt5.12.6 编译部署

安装 qt 查看qt 版本 &#xff1a; qmake -v 下载对应版本 qmqtt 解压下载的mqtt文件 进入qmqtt xxx/src 目录 在qt 安装目录中创建QtMqtt文件夹&#xff0c; &#xff0d; x86平台qt 默认目录为 /usr/include/x86_64-linux-gnu/qt5 &#xff0d; arm平台qt 默认目录为/us…...

阿里ChatSDK使用,开箱即用聊天框

介绍&#xff1a; 效果&#xff1a;智能助理 ChatSDK&#xff0c;是在ChatUI的基础上&#xff0c;结合阿里云智能客服的最佳实践&#xff0c;沉淀和总结出来的一个开箱即用的&#xff0c;可快速搭建智能对话机器人的框架。它简单易上手&#xff0c;通过简单的配置就能搭建出对…...

LangChain —— Message —— How to trim messages

文章目录 一、概述二、获取最后的 max_tokens 令牌三、获取第一个 max_tokens 令牌四、编写自定义令牌计数器五、连成链六、使用 ChatMessageHistory 一、概述 所有模型都有 有限的 上下文窗口&#xff0c;这意味着它们可以作为输入的 token 数量是有限的。如果你有很长的消息&…...

专升本-1.0.3(英语)-升本209天-星期二

自己要耐得住寂寞&#xff0c;守得住自己的初心&#xff0c;守得住自己的未来&#xff0c;然后不断地真实地面对自己&#xff0c;使自己不断地获得一个真实地成长&#xff0c;说真话办真事&#xff0c;自己总会有一条路了&#xff0c;说真话&#xff0c;办真事的那条路才是最为…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...