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

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 目标。

image-20240723173801748

​ 项目地址: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 类图

BehaviourTree_AI

相关文章:

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&#xff0c;实现基…...

Unity-URP-SSAO记录

勾选After Opacity Unity-URP管线&#xff0c;本来又一个“bug”, 网上查不到很多关于ssao的资料 以为会不会又是一个极度少人用的东西 而且几乎都是要第三方替代 也完全没有SSAO大概的消耗是多少&#xff0c;完全是黑盒(因为用的人少&#xff0c;研究的人少&#xff0c;优…...

无人机上磁航技术详解

磁航技术&#xff0c;也被称为地磁导航&#xff0c;是一种利用地球磁场信息来实现导航的技术。在无人机领域&#xff0c;磁航技术主要用于辅助惯性导航系统&#xff08;INS&#xff09;进行航向角的测量与校正&#xff0c;提高无人机的飞行稳定性和准确性。其技术原理是&#x…...

使用 cURL 命令测试网站响应时间

文章目录 使用 cURL 命令测试网站响应时间工具介绍cURL 命令详解命令参数说明输出格式说明示例运行结果总结使用 cURL 命令测试网站响应时间 本文将介绍如何使用 cURL 命令行工具来测试一个网站的响应时间。具体来说,我们将使用 cURL 命令来测量并显示各种网络性能指标,包括 …...

「网络通信」HTTP 协议

HTTP &#x1f349;简介&#x1f349;抓包工具&#x1f349;报文结构&#x1f34c;请求&#x1f34c;响应&#x1f34c;URL&#x1f95d;URL encode &#x1f34c;方法&#x1f34c;报文字段&#x1f95d;Host&#x1f95d;Content-Length & Content-Type&#x1f95d;User…...

科普文:后端性能优化的实战小结

一、背景与效果 ICBU的核心沟通场景有了10年的“积累”&#xff0c;核心场景的界面响应耗时被拉的越来越长&#xff0c;也让性能优化工作提上了日程&#xff0c;先说结论&#xff0c;经过这一波前后端齐心协力的优化努力&#xff0c;两个核心界面90分位的数据&#xff0c;FCP平…...

LeetCode-day23-3098. 求出所有子序列的能量和

LeetCode-day23-3098. 求出所有子序列的能量和 题目描述示例示例1&#xff1a;示例2&#xff1a;示例3&#xff1a; 思路代码 题目描述 给你一个长度为 n 的整数数组 nums 和一个 正 整数 k 。 一个 子序列的 能量 定义为子序列中 任意 两个元素的差值绝对值的 最小值 。 请…...

CSS3雷达扫描效果

CSS3雷达扫描效果https://www.bootstrapmb.com/item/14840 要创建一个CSS3的雷达扫描效果&#xff0c;我们可以使用CSS的动画&#xff08;keyframes&#xff09;和transform属性。以下是一个简单的示例&#xff0c;展示了如何创建一个类似雷达扫描的动画效果&#xff1a; HTM…...

单例模式懒汉模式和饿汉模式

线程安全 单例模式在单线程中&#xff0c;当然是安全的。但是如果在多线程中&#xff0c;由于并行判断&#xff0c;可能会导致创建多个实例。那么如何保证在多线程中单例还是只有一个实例呢? 常见的三种方式: 局部静态变量 原理和饿汉模式相似&#xff0c;利用static只会初始…...

python __repr__和__str__区别

1. __repr__ __repr__ 方法由 repr() 内置函数调用&#xff0c;用于计算对象的“正式”字符串表示形式。理想情况下&#xff0c;这个字符串应该看起来像一个有效的 Python 表达式&#xff0c;可以在适当的环境下用来重新创建具有相同值的对象。如果这不可能实现&#xff0c;那…...

huawei USG6001v1学习----NAT和智能选路

目录 1.NAT的分类 2.智能选路 1.就近选路 2.策略路由 3.智能选路 NAT:&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09; 指网络地址转换&#xff0c;1994年提出的。NAT是用于在本地网络中使用私有地址&#xff0c;在连接互联网时转而使用全局…...

FPGA JTAG最小系统 EP2C5T144C8N

FPGA的文档没有相应的基础还真不容易看懂&#xff0c;下面是B站上对FPGA文档的解读(本文非对文档解读&#xff0c;只是为个人记录第三期&#xff1a;CycloneIV E最小系统板设计&#xff08;一&#xff09;从Datasheet上获取FPGA的基本参数_哔哩哔哩_bilibili 电源部份 核心电…...

Android 15 之如何快速适配 16K Page Size

在此之前&#xff0c;我们通过 《Android 15 上 16K Page Size 为什么是最坑》 介绍了&#xff1a; 什么是16K Page Size为什么它对于 Android 很坑如何测试 如果你还没了解&#xff0c;建议先去了解下前文&#xff0c;然后本篇主要是提供适配的思路&#xff0c;因为这类适配…...

学习unity官方的网络插件Netcode【一】

对bool值的个人理解&#xff1a; using Unity.Netcode; using UnityEngine; //个人理解&#xff1a;通过Rpc完成了一次客户端给服务端发消息&#xff0c;服务端再向所有客户端广播消息 public class RpcTest : NetworkBehaviour {public override void OnNetworkSpawn(){if (!…...

QT写一个mainWindow

切换风格的写法&#xff1a; 先看看样式效果&#xff1a; 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 …...

洗地机哪个牌子好?四款口碑最好的洗地机排名推荐

随着“懒人经济”的出现&#xff0c;越来越多的人开始使用洗地机。洗地机哪个牌子好&#xff1f;为了帮助大家在这个琳琅满目的市场中做出明智决策&#xff0c;本文特别整理了四款口碑最好的洗地机排名推荐&#xff0c;它们凭借出色的清洁效果、智能化的操作体验以及用户的高度…...

如何提升短视频的曝光量和获客效能?云微客来解决

在流量至上的当下&#xff0c;短视频凭借其优势&#xff0c;迅速成为了众多企业获客引流的核心营销手段。进入短视频赛道后&#xff0c;如何提升短视频的曝光量和获客效能&#xff0c;就成为了众多企业亟待解决的焦点。 如果你不想投入大量的广告预算&#xff0c;还想在短视频平…...

SpringBoot开发中如何缓存数据, 减少数据库的访问频率?

一&#xff1a;自定义是否开启缓存 方法一&#xff1a; 在不同环境的配置文件中如application-dev.yml、application-test.yml、application-prod.yml&#xff0c;修改 spring.cache.type none; spring:cache:type: none 方法二&#xff1a; 自定义配置 application.yml&…...

PostgreSQL如何在windows/linux开启归档

linux开启归档&#xff1a; archive_mode onarchive_command test ! -f /mnt/pg12/archivedir/%f && cp %p /mnt/pg12/archivedir/%fwindows开启归档&#xff1a; archive_mode onarchive_command copy "%p" "C:\\server\\pg12\\archivedir\\%f&q…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...