2024-07-23 Unity AI行为树2 —— 项目介绍
文章目录
- 1 项目介绍
- 2 AI 代码介绍
- 2.1 BTBaseNode / BTControlNode
- 2.2 动作/条件节点
- 2.3 选择 / 顺序节点
- 3 怪物实现
- 4 其他功能
- 5 UML 类图
项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。
1 项目介绍
本项目使用 Unity 2022.3.32f1c1,实现基本的 AI 框架。其中,用 Cube(红色)代替怪物模型,Cube(蓝色)代替玩家,即 AI 目标。
项目地址:https://github.com/zheliku/BehaviourTree_AI。
2 AI 代码介绍
2.1 BTBaseNode / BTControlNode
所有结点都需要执行各自的任务,因此提取到基类节点中:
/// <summary>
/// 行为树结点基类
/// </summary>
public abstract class BTBaseNode
{/// <summary>/// 执行节点逻辑的抽象方法/// </summary>public abstract ENodeState Execute();
}
而控制节点需要知道其控制哪些节点,因此相关内容需要提取到控制节点的基类中:
using System.Collections.Generic;public abstract class BTControlNode : BTBaseNode
{// 存储子节点的 Listprotected List<BTBaseNode> _childList = new List<BTBaseNode>();protected int _currentIndex = 0; // 当前执行到的子节点索引/// <summary>/// 添加子节点/// </summary>public virtual void AddChild(params BTBaseNode[] node) {_childList.AddRange(node);}
}
2.2 动作/条件节点
动作节点执行具体的行为,没有子节点。
执行完行为后,可以返回是否执行成功,因此需要外部添加执行的方法。
using System;/// <summary>
/// 动作节点,执行具体行为,没有子节点
/// </summary>
public class BTActionNode : BTBaseNode
{private Func<bool> _action; // 返回值表示执行是否成功public BTActionNode(Func<bool> action) { _action = action; }public override ENodeState Execute() {if (_action == null) return ENodeState.Failure;// 执行行为return _action.Invoke() ? ENodeState.Success : ENodeState.Failure; }
}
条件节点用于评估条件,根据条件结果返回成功 / 失败。
和动作节点类似,也需要外部提供判断条件的方法。
using System;/// <summary>
/// 条件节点,评估一个条件,并返回成功 / 失败
/// </summary>
public class BTConditionNode : BTBaseNode
{private Func<bool> _action; // 返回值表示执行是否成功public BTConditionNode(Func<bool> action) { _action = action; }public override ENodeState Execute() {if (_action == null) return ENodeState.Failure;// 执行行为return _action.Invoke() ? ENodeState.Success : ENodeState.Failure; }
}
2.3 选择 / 顺序节点
选择 / 顺序节点都仅依据子节点的状态,返回自己的状态。因此只需要实现 Execute() 方法即可,区别在于实现的逻辑不同。
using System;/// <summary>
/// 选择节点<br/>
/// 特点:<br/>
/// 1. 按顺序执行子节点<br/>
/// 2. 如果某子节点返回成功,则返回成功,不执行后续结点<br/>
/// 3. 如果某子节点返回失败,则继续执行下一个子节点
/// </summary>
public class BTSelectNode : BTControlNode
{public override ENodeState Execute() {var childNode = _childList[_currentIndex];var result = childNode.Execute();switch (result) {case ENodeState.Success: { // 成功,则重置索引,直接返回_currentIndex = 0;return ENodeState.Success;}case ENodeState.Failure: { // 失败,则继续下一个节点++_currentIndex;if (_currentIndex == _childList.Count) { // 执行到最后,重置索引_currentIndex = 0;return ENodeState.Failure;}break;}case ENodeState.Running: {return ENodeState.Running;}default: throw new ArgumentOutOfRangeException();}// 没有执行完,或者节点失败,才执行该逻辑// 此时仍希望下一帧继续往后执行,因此返回成功return ENodeState.Success;}
}/// <summary>
/// 序列节点<br/>
/// 特点:<br/>
/// 1. 按顺序执行子节点<br/>
/// 2. 只要有一个子节点返回失败,则整个节点返回失败<br/>
/// 3. 所有子节点都返回成功,则整个节点返回成功
/// </summary>
public class BTSequenceNode : BTControlNode
{public override ENodeState Execute() {var childNode = _childList[_currentIndex];var result = childNode.Execute();switch (result) {case ENodeState.Success: { // 成功,则继续下一个节点++_currentIndex;if (_currentIndex == _childList.Count) { // 执行到最后,重置索引_currentIndex = 0;return ENodeState.Success;}break;}case ENodeState.Failure: { // 失败,则重置索引,直接返回_currentIndex = 0;return ENodeState.Failure;}case ENodeState.Running: {return ENodeState.Running;}default: throw new ArgumentOutOfRangeException();}return ENodeState.Success;}
}
3 怪物实现
类似 2024-07-12 Unity AI状态机1 —— 框架介绍_有限状态机编程框架-CSDN博客 中的怪物实现,但将怪物数据写在各个行为的控制类中,因此具有以下 4 个控制类:
- PatrolControl(巡逻)
- ChaseControl(追逐)
- AttackControl(攻击)
- BackControl(返回)
其余实现基本一致。
4 其他功能
为了辅助绘图,在 Monster 类中的 Update 方法里判断当前执行的行为 / 状态。用二进制位表示每个状态,异或运算来计算当前的状态:
private void Update() {_btAIRoot.Execute(); // 执行行为树switch (CurrentState) { // 依据当前行为绘制辅助线case 1:AttackCtrl.DrawGizmos();break;case 2:BackCtrl.DrawGizmos();break;case 4:ChaseCtrl.DrawGizmos();break;case 8:PatrolCtrl.DrawGizmos();break;}
}
5 UML 类图

相关文章:
2024-07-23 Unity AI行为树2 —— 项目介绍
文章目录 1 项目介绍2 AI 代码介绍2.1 BTBaseNode / BTControlNode2.2 动作/条件节点2.3 选择 / 顺序节点 3 怪物实现4 其他功能5 UML 类图 项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。 1 项目介绍 本项目使用 Unity 2022.3.32f1c1,实现基…...
Unity-URP-SSAO记录
勾选After Opacity Unity-URP管线,本来又一个“bug”, 网上查不到很多关于ssao的资料 以为会不会又是一个极度少人用的东西 而且几乎都是要第三方替代 也完全没有SSAO大概的消耗是多少,完全是黑盒(因为用的人少,研究的人少,优…...
无人机上磁航技术详解
磁航技术,也被称为地磁导航,是一种利用地球磁场信息来实现导航的技术。在无人机领域,磁航技术主要用于辅助惯性导航系统(INS)进行航向角的测量与校正,提高无人机的飞行稳定性和准确性。其技术原理是&#x…...
使用 cURL 命令测试网站响应时间
文章目录 使用 cURL 命令测试网站响应时间工具介绍cURL 命令详解命令参数说明输出格式说明示例运行结果总结使用 cURL 命令测试网站响应时间 本文将介绍如何使用 cURL 命令行工具来测试一个网站的响应时间。具体来说,我们将使用 cURL 命令来测量并显示各种网络性能指标,包括 …...
「网络通信」HTTP 协议
HTTP 🍉简介🍉抓包工具🍉报文结构🍌请求🍌响应🍌URL🥝URL encode 🍌方法🍌报文字段🥝Host🥝Content-Length & Content-Type🥝User…...
科普文:后端性能优化的实战小结
一、背景与效果 ICBU的核心沟通场景有了10年的“积累”,核心场景的界面响应耗时被拉的越来越长,也让性能优化工作提上了日程,先说结论,经过这一波前后端齐心协力的优化努力,两个核心界面90分位的数据,FCP平…...
LeetCode-day23-3098. 求出所有子序列的能量和
LeetCode-day23-3098. 求出所有子序列的能量和 题目描述示例示例1:示例2:示例3: 思路代码 题目描述 给你一个长度为 n 的整数数组 nums 和一个 正 整数 k 。 一个 子序列的 能量 定义为子序列中 任意 两个元素的差值绝对值的 最小值 。 请…...
CSS3雷达扫描效果
CSS3雷达扫描效果https://www.bootstrapmb.com/item/14840 要创建一个CSS3的雷达扫描效果,我们可以使用CSS的动画(keyframes)和transform属性。以下是一个简单的示例,展示了如何创建一个类似雷达扫描的动画效果: HTM…...
单例模式懒汉模式和饿汉模式
线程安全 单例模式在单线程中,当然是安全的。但是如果在多线程中,由于并行判断,可能会导致创建多个实例。那么如何保证在多线程中单例还是只有一个实例呢? 常见的三种方式: 局部静态变量 原理和饿汉模式相似,利用static只会初始…...
python __repr__和__str__区别
1. __repr__ __repr__ 方法由 repr() 内置函数调用,用于计算对象的“正式”字符串表示形式。理想情况下,这个字符串应该看起来像一个有效的 Python 表达式,可以在适当的环境下用来重新创建具有相同值的对象。如果这不可能实现,那…...
huawei USG6001v1学习----NAT和智能选路
目录 1.NAT的分类 2.智能选路 1.就近选路 2.策略路由 3.智能选路 NAT:(Network Address Translation,网络地址转换) 指网络地址转换,1994年提出的。NAT是用于在本地网络中使用私有地址,在连接互联网时转而使用全局…...
FPGA JTAG最小系统 EP2C5T144C8N
FPGA的文档没有相应的基础还真不容易看懂,下面是B站上对FPGA文档的解读(本文非对文档解读,只是为个人记录第三期:CycloneIV E最小系统板设计(一)从Datasheet上获取FPGA的基本参数_哔哩哔哩_bilibili 电源部份 核心电…...
Android 15 之如何快速适配 16K Page Size
在此之前,我们通过 《Android 15 上 16K Page Size 为什么是最坑》 介绍了: 什么是16K Page Size为什么它对于 Android 很坑如何测试 如果你还没了解,建议先去了解下前文,然后本篇主要是提供适配的思路,因为这类适配…...
学习unity官方的网络插件Netcode【一】
对bool值的个人理解: using Unity.Netcode; using UnityEngine; //个人理解:通过Rpc完成了一次客户端给服务端发消息,服务端再向所有客户端广播消息 public class RpcTest : NetworkBehaviour {public override void OnNetworkSpawn(){if (!…...
QT写一个mainWindow
切换风格的写法: 先看看样式效果: mian_window.h文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();void Ini…...
Java查找算法练习(2024.7.23)
顺序查找 package SearchExercise20240723; import java.util.Scanner; public class SearchExercise {public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println("需要多大的数组?");int size sc.nextInt();int[] array …...
洗地机哪个牌子好?四款口碑最好的洗地机排名推荐
随着“懒人经济”的出现,越来越多的人开始使用洗地机。洗地机哪个牌子好?为了帮助大家在这个琳琅满目的市场中做出明智决策,本文特别整理了四款口碑最好的洗地机排名推荐,它们凭借出色的清洁效果、智能化的操作体验以及用户的高度…...
如何提升短视频的曝光量和获客效能?云微客来解决
在流量至上的当下,短视频凭借其优势,迅速成为了众多企业获客引流的核心营销手段。进入短视频赛道后,如何提升短视频的曝光量和获客效能,就成为了众多企业亟待解决的焦点。 如果你不想投入大量的广告预算,还想在短视频平…...
SpringBoot开发中如何缓存数据, 减少数据库的访问频率?
一:自定义是否开启缓存 方法一: 在不同环境的配置文件中如application-dev.yml、application-test.yml、application-prod.yml,修改 spring.cache.type none; spring:cache:type: none 方法二: 自定义配置 application.yml&…...
PostgreSQL如何在windows/linux开启归档
linux开启归档: archive_mode onarchive_command test ! -f /mnt/pg12/archivedir/%f && cp %p /mnt/pg12/archivedir/%fwindows开启归档: archive_mode onarchive_command copy "%p" "C:\\server\\pg12\\archivedir\\%f&q…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
uni-app学习笔记二十七--设置底部菜单TabBar的样式
官方文档地址:uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容,通常写在项目的App.vue的onLaunch方法中,用于项目启动时立即执行 重要参数: indexnumber是tabBar 的哪一项&…...
SDU棋界精灵——硬件程序ESP32实现opus编码
一、 音频处理框架 该项目基于Espressif的音频处理框架构建,核心组件包括 ESP-ADF 和 ESP-SR,以下是完整的音频处理框架实现细节: 1.核心组件 (1) 音频前端处理 (AFE - Audio Front-End) main/components/audio_pipeline/afe_processor.c功能: 声学回声…...
2025-06-01-Hive 技术及应用介绍
Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具,它为海量结构化数据提供类 SQL 的查询能力…...
