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 目标。
项目地址:https://github.com/zheliku/StateMachine_AI。
2 模块介绍
2.1 BaseState
在框架介绍的基础上,添加了两个方法:
-
DistanceOfXZ(Vector3, Vector3)
用于计算 xz 平面上的距离(不考虑 y 轴方向)。
-
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:路径移动巡逻的数据。
-
Stay:
原地播放某个动作,因此需要 AI 动作枚举。目前只添加 Sleep 动作。
public enum EAction {Sleep, } -
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 类图

相关文章:
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机器并执行命令
需求:我们需要从11.0.1.17远程到11.0.1.16上执行命令 实现: 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服务启动与停止(Windows)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,可以按照以下步骤进行操作: 创建一个Spring Boot项目,并添加所需的依赖。在pom.xml文件中添加Spring Boot、Spring Security、Redis、MySQL和MyBatis的依赖项。 …...
微调 Florence-2 - 微软的尖端视觉语言模型
Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力,因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。 Florence 开箱即用支持多种类型的任务,包括: 看图说话、目标检测、OCR 等等。虽然覆盖面…...
【数据结构】二叉树全攻略,从实现到应用详解
💎所属专栏:数据结构与算法学习 💎 欢迎大家互三:2的n次方_ 🍁1. 树形结构的介绍 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做…...
微信小程序加载动画文件
最近在做微信小程序的动画,调研了几种方案 PAG 腾讯自家的,分为完整版和lite版,对于矢量动画挺好的,但是位图会有问题 完整版会逐渐卡死,lite虽然不会卡死,但是很模糊,优点是动画文件很的很小。…...
[计算机网络] VPN技术
VPN技术 1. 概述 虚拟专用网络(VPN)技术利用互联网服务提供商(ISP)和网络服务提供商(NSP)的网络基础设备,在公用网络中建立专用的数据通信通道。VPN的主要优点包括节约成本和提供安全保障。 优…...
SQL 中的 EXISTS 子句:探究其用途与应用
目录 EXISTS 子句简介语法 EXISTS 与 NOT EXISTSEXISTS 子句的工作原理实际应用场景场景一:筛选存在关联数据的记录场景二:优化查询性能 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,层叠样式表)是一种是一种用来为结构化文档(如 HTML 文档)添加样式(字体、间距和颜色等)的计算机语言,能够对网页中元素位置的排版进行像素级别的精…...
Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战
Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,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
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 介绍 像 MySQL 这样的关系型数据库管理系统在许多网站和应用程序中都是必不可少的。然而,并非所有用户都习惯通过命令行来管…...
redis存入hash,key=>value和key=>(key=>value)使用Python举例
在 Redis 中,HASH 数据结构(也称为 HMAP 或 Hash Map)允许你存储键值对集合,其中每个键值对都是字段(field)和值(value)的映射。在 Python 中,你可以使用 redis-py 库来与…...
Guava LocalCache源码分析:LocalCache的get、put、expand、refresh、remove、clear、cleanUp
Guava LocalCache源码分析:LocalCache的get、put、expand 前言一、get二、put三、expand 前言 上篇文章,详细描写了Guava LocalCache怎样如ConcurrentHashMap对缓存数据进行了分段存储。本章主要针对LocalCache重要的几个接口进行说明。 一、get CanIg…...
linux-arm ubuntu18.04 qmqtt5.12.6 编译部署
安装 qt 查看qt 版本 : qmake -v 下载对应版本 qmqtt 解压下载的mqtt文件 进入qmqtt xxx/src 目录 在qt 安装目录中创建QtMqtt文件夹, - x86平台qt 默认目录为 /usr/include/x86_64-linux-gnu/qt5 - arm平台qt 默认目录为/us…...
阿里ChatSDK使用,开箱即用聊天框
介绍: 效果:智能助理 ChatSDK,是在ChatUI的基础上,结合阿里云智能客服的最佳实践,沉淀和总结出来的一个开箱即用的,可快速搭建智能对话机器人的框架。它简单易上手,通过简单的配置就能搭建出对…...
LangChain —— Message —— How to trim messages
文章目录 一、概述二、获取最后的 max_tokens 令牌三、获取第一个 max_tokens 令牌四、编写自定义令牌计数器五、连成链六、使用 ChatMessageHistory 一、概述 所有模型都有 有限的 上下文窗口,这意味着它们可以作为输入的 token 数量是有限的。如果你有很长的消息&…...
专升本-1.0.3(英语)-升本209天-星期二
自己要耐得住寂寞,守得住自己的初心,守得住自己的未来,然后不断地真实地面对自己,使自己不断地获得一个真实地成长,说真话办真事,自己总会有一条路了,说真话,办真事的那条路才是最为…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
