当前位置: 首页 > 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
http://www.lryc.cn/news/405613.html

相关文章:

  • Unity-URP-SSAO记录
  • 无人机上磁航技术详解
  • 使用 cURL 命令测试网站响应时间
  • 「网络通信」HTTP 协议
  • 科普文:后端性能优化的实战小结
  • LeetCode-day23-3098. 求出所有子序列的能量和
  • CSS3雷达扫描效果
  • 单例模式懒汉模式和饿汉模式
  • python __repr__和__str__区别
  • huawei USG6001v1学习----NAT和智能选路
  • FPGA JTAG最小系统 EP2C5T144C8N
  • Android 15 之如何快速适配 16K Page Size
  • 学习unity官方的网络插件Netcode【一】
  • QT写一个mainWindow
  • Java查找算法练习(2024.7.23)
  • 洗地机哪个牌子好?四款口碑最好的洗地机排名推荐
  • 如何提升短视频的曝光量和获客效能?云微客来解决
  • SpringBoot开发中如何缓存数据, 减少数据库的访问频率?
  • PostgreSQL如何在windows/linux开启归档
  • 【启明智显分享】基于国产Model3芯片的7寸触摸屏助力智慧医疗,电子床头屏提升护理交互
  • 从理论到实践:如何用 TDengine 打造完美数据模型​
  • 可以免费合并pdf的软件 合并pdf文件的软件免费 合并pdf的软件免费
  • 【排序 滑动窗口 】1498. 满足条件的子序列数目
  • RabbitMQ普通集群搭建指南
  • AGV平面坐标系变换公式及实例
  • es切片和集群
  • IEEE官方列表会议 | 第三届能源与环境工程国际会议(CFEEE 2024)
  • 深度学习中的正则化技术 - Dropout篇
  • 《昇思 25 天学习打卡营第 18 天 | 扩散模型(Diffusion Models) 》
  • 【Django+Vue3 线上教育平台项目实战】Elasticsearch实战指南:从基础到构建课程搜索与数据同步接口