新闻中心
C++如何实现一个简单的行为树_C++游戏AI中决策逻辑的行为树实现
行为树通过节点组合实现清晰的AI逻辑,核心包含动作、条件和控制节点,利用Success、Failure、Running状态驱动执行,序列与选择节点协调子节点顺序,配合黑板系统可扩展复杂行为,适合游戏NPC决策。

在C++游戏AI开发中,行为树(Beh*ior Tree)是一种广泛使用的决策系统,用于组织和控制NPC的智能行为。相比状态机,行为树结构更清晰、扩展性更强,适合处理复杂的AI逻辑。实现一个简单的行为树并不复杂,关键在于理解其核心节点类型和执行机制。
行为树的基本概念
行为树由节点构成,每个节点返回三种状态之一:成功(Success)、失败(Failure)、运行中(Running)。常见节点类型包括:
- 动作节点(Action):执行具体操作,如“攻击”、“移动”
- 条件节点(Condition):判断某个条件是否成立,如“血量低于50%”
- 控制节点(Control):管理子节点的执行顺序,如序列节点(Sequence)、选择节点(Selector)
定义节点基类
所有节点都继承自一个公共基类,提供统一的执行接口:
enum class NodeStatus {
Success,
Failure,
Running
};
<p>class Beh*iorNode {
public:
virtual NodeStatus Execute() = 0;
virtual ~Beh*iorNode() = default;
};</p>实现控制节点
控制节点负责调度子节点。例如,序列节点依次执行子节点,任一失败则整体失败;选择节点则尝试下一个子节点直到成功。
class SequenceNode : public Beh*iorNode {
public:
void AddChild(Beh*iorNode* child) {
children.push_back(child);
}
<pre class='brush:php;toolbar:false;'>NodeStatus Execute() override {
for (auto& child : children) {
NodeStatus status = child->Execute();
if (status == NodeStatus::Failure) {
return NodeStatus::Failure;
}
if (status == NodeStatus::Running) {
return NodeStatus::Running;
}
}
return NodeStatus::Success;
}private:
std::vector
class SelectorNode : public Beh*iorNode { public: void AddChild(Beh*iorNode* child) { children.push_back(child); }
NodeStatus Execute() override {
for (auto& child : children) {
NodeStatus status = child->Execute();
if (status == NodeStatus::Success) {
return NodeStatus::Success;
}
if (status == NodeStatus::Running) {
return NodeStatus::Running;
}
}
return NodeStatus::Failure;
}private:
std::vector
实现动作与条件节点
动作节点封装具体行为。例如:
GoEnhance
全能AI视频制作平台:通过GoEnhance AI让视频创作变得比以往任何时候都更简单。
347
查看详情
class MoveToPlayer : public Beh*iorNode {
public:
NodeStatus Execute() override {
// 模拟移动逻辑
std::cout << "Moving towards player...\n";
return NodeStatus::Success; // 简化:一步完成
}
};
<p>class IsPlayerInRange : public Beh*iorNode {
public:
explicit IsPlayerInRange(bool& inRange) : inRange_(inRange) {}</p><pre class='brush:php;toolbar:false;'>NodeStatus Execute() override {
return inRange_ ? NodeStatus::Success : NodeStatus::Failure;
}private: bool& inRange_; };
构建并运行行为树
使用上述节点组合出一个简单的AI行为:如果玩家在范围内,则攻击,否则靠近。
int main() {
bool playerInRange = false;
<pre class='brush:php;toolbar:false;'>IsPlayerInRange condition(playerInRange);
MoveToPlayer moveAction;
AttackPlayer attackAction; // 假设已
定义
SequenceNode approachSequence;
approachSequence.AddChild(&condition);
approachSequence.AddChild(&attackAction);
SelectorNode root;
root.AddChild(&approachSequence);
root.AddChild(&moveAction);
// 模拟执行
playerInRange = false;
root.Execute(); // 输出: Moving towards player...
playerInRange = true;
root.Execute(); // 输出: Attacking player!
return 0;}
基本上就这些。通过组合不同类型的节点,可以构建出层次清晰、易于维护的游戏AI决策逻辑。实际项目中可加入装饰节点(如取反、重试)、黑板系统(共享数据)来增强灵活性。不复杂但容易忽略的是状态的持续跟踪,比如“Running”状态需要保留执行上下文,以便下一帧继续。
以上就是C++如何实现一个简单的行为树_C++游戏AI中决策逻辑的行为树实现的详细内容,更多请关注其它相关文章!
# 三种
# 济南营销网络推广介绍语
# 智能网站建设基本流程
# 商务网站建设优化软件
# 库巴购物网站建设
# 黑皮甘蔗营销推广方案
# 峨边企业网站推广
# 辉县网站建设电话
# 武宁网站关键词推广
# 辽源seo入门是什么网站
# 天门网站建设批发价
# 解决问题
# node
# 中文网
# 相关文章
# 是一种
# 与其他
# 的是
# 如何使用
# 下一
# 如何实现
# c++
# ai
# app
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
Golang如何测试channel通信行为_Golang channel通信测试与分析方法
AO3镜像入口大全 AO3网页版内容访问全集
C++如何实现单例模式_C++设计模式之线程安全的单例写法
Golang如何使用context实现超时取消_Golang context超时取消模式实践
1688商家版怎样分析买家画像精准供货_1688商家版分析买家画像精准供货【供货策略】
12306选座怎么选到临时改签座_12306改签选座策略与步骤
小米14应用无法联网原因分析_小米14网络权限修复
css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容
如何在J*a中使用Locale处理多语言环境
126邮箱网页版官方入口 126邮箱账号在线登录平台
Yandex官网免登录入口_俄罗斯Yandex搜索引擎一键访问
Centos/Linux 系统下安装 composer 的完整步骤
小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】
我的世界官方游戏入口 我的世界官网平台直达链接
PHP 枚举:根据字符串获取枚举案例的策略与实现
Sublime Text怎么显示空格和制表符_Sublime显示不可见字符设置
Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践
抖音网页版企业服务中心登录入口_抖音网页版企业登录平台
企业名称高精度匹配:N-gram方法在结构相似性分析中的应用
Python实时数据流中的动态最值查找策略
PySpark中从现有列右侧提取可变长度字符创建新列的教程
可靠CSGO开箱平台解析 CSGO开箱网合集
支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡
顺丰国际快递查询 国际件官方查询入口
Lar*el Excel导入时生成自定义递增ID的策略与实践
j*a toString()的覆盖
生成rdflib自定义SPARQL函数:参数匹配与实践指南
文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】
Win10双系统截图高效法 截屏快捷键速记【技巧】
Go语言中动态执行代码字符串的策略与实践
html网页设计源代码怎么运行_运行html网页设计源代码步骤【指南】
Pyrogram与g4f集成:异步编程实践与常见错误解决
mcjs网页版流畅运行 mcjs低配电脑畅玩入口
css滚动区域卡顿如何改善_css滚动问题用will-change优化渲染
蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗
品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程
解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南
Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南
C++ string find函数返回值npos详解_C++字符串查找失败的判断条件
FullCalendar 自定义按钮样式定制指南
Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】
XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法
如何使用Go和Martini动态服务解码后的图片
c++项目目录结构应该如何组织_c++工程化项目结构规范
qq游戏免费畅玩入口_qq游戏电脑版快速启动
QQ邮箱登录官网首页 腾讯QQ邮箱网页入口
jQuery Mask 插件中实现电话号码固定前导零的教程
Lar*el递归关系中排除子孙节点的策略


2025-12-03
浏览次数:次
返回列表
定义
SequenceNode approachSequence;
approachSequence.AddChild(&condition);
approachSequence.AddChild(&attackAction);
SelectorNode root;
root.AddChild(&approachSequence);
root.AddChild(&moveAction);
// 模拟执行
playerInRange = false;
root.Execute(); // 输出: Moving towards player...
playerInRange = true;
root.Execute(); // 输出: Attacking player!
return 0;