C++在游戏开发中的AI行为树

为啥是行为树?说白了,它就是用来替代传统"状态机"那坨又臭又长的if-else和switch-case的。以前写个复杂点的AI,状态一多,那代码简直没法看,各个状态之间跳转的线能把你绕晕,后期想加个新行为?动不动就牵一发而动全身,调试起来更是要了老命。行为树不一样,它用树状结构来组织AI的行为逻辑,节点类型清晰,职责分明,无论是设计、实现还是调试,都优雅了不止一个档次。

行为树的核心在于它的节点。咱们掰开揉碎了说,主要就分三大类:控制节点、条件节点和行为节点。

控制节点,顾名思义,就是管流程的,相当于树干和树枝。最常见的有这么几个:

序列节点:按顺序执行子节点,一个失败了,整个序列就失败。比如"走近玩家->攻击->后退"这一套连招,用序列节点组织就非常合适。

选择节点:挨个执行子节点,直到有一个成功为止。比如怪物决定下一步干啥:"有敌人?->攻击";"没敌人但饿了?->找吃的";"否则?->发呆"。这就是选择节点的典型应用。

并行节点:同时执行所有子节点,用来处理需要同时进行的动作,比如一边移动一边播放跑步动画。

条件节点,就是做判断的,相当于AI的感知器官。比如"玩家在视野内吗?"、"血量低于20%了吗?",它返回的就是成功或失败,直接影响控制节点的决策流向。

行为节点,就是最终执行具体动作的叶子节点,是AI真正去做的事。比如"移动到A点"、"播放攻击动画"、"吃药回血"。

在C++里实现行为树,面向对象的思想就派上大用场了。我们可以定义一个抽象的基类,里面就一个虚函数。然后所有的具体节点类型,比如、,都从这个基类继承,并重写自己的逻辑。这样,整棵树执行起来,就是从根节点开始,递归地调用各个子节点的,结构清晰得一匹。

这里有个实战中非常关键的概念------黑板。你可以把它理解成一个公共的数据黑板,各个节点都能往上读数据和写数据。比如,一个"发现敌人"的条件节点,可以把敌人的坐标写到黑板上;然后后面的"移动"行为节点,再从黑板上读取这个坐标,作为自己的移动目标。这样就实现了节点之间的数据共享和解耦,妙啊!

光说不练假把式,举个简单的例子。假设我们要实现一个哨兵敌人的AI:

根节点是一个选择节点。

选择节点的第一个子节点是一个序列节点,用于处理"发现敌人并攻击"的逻辑。这个序列节点包含:条件节点"是否有敌人在视野内?" -> 行为节点"移动到敌人身边" -> 行为节点"攻击"。

选择节点的第二个子节点是一个序列节点,用于处理"巡逻"逻辑。包含:行为节点"移动到巡逻点A" -> 行为节点"移动到巡逻点B",如此循环。

用代码骨架表示大概是这样:

当然了,真在项目里用,还得考虑很多优化。比如节点对象的频繁创建和销毁会影响性能,通常我们会用对象池来管理节点。行为树的编辑如果全靠手写代码,策划同事肯定会提刀来找你,所以一般都会配套开发一个可视化的编辑器,让策划能拖拖拽拽就把树搭起来,然后导出成数据文件,游戏运行时再加载构建。

总而言之,用C++撸行为树,核心就是利用其高效的性能和对面向对象的强大支持,构建出一个可维护、可扩展、逻辑清晰的AI框架。这东西上手后,你会发现写游戏AI不再是痛苦的折磨,而变成了一种结构化的设计乐趣。好了,今天的水就灌到这里,希望对各位老铁有帮助,有啥问题评论区见!

相关推荐
张张123y10 小时前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
wo_jack11 小时前
C++ 入门笔记(十六):第16课 vector 模拟实现十问十答 —— 从三指针到迭代器失效
c++·后端·面试·stl·vector
D e re k ZH12 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶13 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
FRing0313 小时前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
雪落漂泊13 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
波力海苔夹心脆67514 小时前
C# WPF 资源字典详解:ResourceDictionary、MergedDictionaries 与自定义控件案例
开发语言·c#·wpf·入门教程·resource·资源字典
不会算法的笨小孩14 小时前
异常的使用以及会出现的问题
开发语言·c++·c++11·异常
Hhy_110716 小时前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
starzy199017 小时前
深入理解Scala函数定义:从方法到函数的类型跨越
开发语言·scala