‫你好, 欢迎｡
‫这节课, 我们将用C++实现一个shoot节点, 让我们的敌人变得更有威胁｡
‫让我们一起来看看怎么做吧｡
‫所以我们的行为树中明显缺少的一项功能就是射击的能力｡
‫我最理想的做法是移动到玩家的位置, 然后开枪｡
‫但我们想先稍微改变一下我们的运动方式｡
‫我需要调整几个方面, 如果选择“移动到节点”, 则需要更改的一个方面是半径｡
‫我不想让敌人直接靠近我, 所以如果我改变可接受的半径,
‫那么它将在离我五米远的地方停止移动｡
‫所以它会停止｡
‫给予我五米的距离｡
‫他朝我走过来, 就这样｡
‫他停下来盯着我｡
‫现在我想做的另一件事是在黑板部分, 你可以看到有一个观察到的黑板值｡
‫如果我们没有检查, 让我们看看我移动时会发生什么｡
‫他基本上, 这是稍微更明显, 当我们有一个较小的可接受的半径｡
‫所以我们现在把它降到54｡
‫如果我点击播放, 那么你可以看到我的移动｡
‫他去了我的最后一个位置, 然后他只有当他到达那里, 他来更新｡
‫这不是我们想要的
‫我们想要的是它不断地向我们走来｡
‫如果你检查观察黑板值, 那么它的意思就是每次玩家位置改变,
‫我们都会更新我们的移动位置.
‫所以如果我点击播放和移动, 你可以看到他一直在跟着我, 更新他的路径｡
‫这正是我们想要的｡
‫现在我们可以将接受半径更改为500, 这样就不那么明显了｡
‫但是我们仍然可以观察到黑板上的值｡
‫然后我们想要的行为是一旦他进入我们的半径范围内, 就像这样, 他会停下来向我们开枪｡
‫为此, 我们需要一种新的任务｡
‫所以我们要在这里创建一个新的C++任务｡
‫所以我们要添加一个新的C++类｡
‫然后我们将显示所有类并查找节拍任务｡
‫现在, 我们需要哪一个, 节拍任务节点还是节拍任务黑板库？
‫其实我们并不需要用钥匙因为我们只要试着开枪就行了.
‫这就是我们要做的｡
‫我们要扣动扳机, 否则瞄准将在行为树的其他地方完成｡
‫我们打开task节点, 这里是基类, 我们将把它命名为beat task.
‫下划线｡
‫开枪啊
‫让我们继续创建该类｡
‫然后我们就得到了这样的结果｡
‫所以我们要做同样的设置｡
‫因此, 对你们来说, 有一个小小的挑战, 就是做同样的设置, 就像我们的黑板一样,
‫清晰的黑板值｡
‫我们希望有一个名称, 我们希望有一个执行任务｡
‫现在假设视频并尝试一下｡
‫好的欢迎回来｡
‫所以这是一个小任务｡
‫我只需要把签名从一个干净的黑板上复制过来, 包括公共和受保护的部分｡
‫我将更改构造函数的名称｡
‫我将继续执行并实现我们的构造函数｡
‫我们需要做什么？
‫我们需要将节点名称设置为shoot｡
‫我们就这么称呼它｡
‫然后回到shoot任务的header, 我们现在要尝试实现execute任务, 我们只需要调用super｡
‫我将从clear blackboard值CP文件中复制该值, 然后我们就可以开始实施了｡
‫首先我们要做的是, 让我们有更多的空间我们要抓住棋子.
‫我们为什么要抓到我们的棋子？
‫好吧, 让我们来看看射手角色, 它是一个棋子｡
‫还记得那个枪手吗
‫点H有一个拍摄方法｡
‫这就是我们想要称之为“我们”的东西, 本质上和玩家所做的一样｡
‫他按住了扳机按钮, 这就是射击方法.
‫我们希望人工智能也能这样做｡
‫当你有射击任务时, 它会按住触发按钮或反复按下该触发按钮,
‫这样执行任务就可以完成这项任务｡
‫我们可能会返回这里的值, 因为记住, 这个动作只有一次｡
‫这不是连续射击｡
‫我们该怎么办？
‫如果我们或成功, 我们将返回ET节点结果成功｡
‫如果我们成功了, 因为我们不需要不断地冷静滴答｡
‫我们不需要此任务运行超过一帧的时间｡
‫我们需要做的另一件事是, 就像我说的, 掌握典当类｡
‫我接下来要做的是向你们展示如何使用人工智能控制器｡
‫从AI控制器中, 我们知道我们可以调用get pawn来获取被控制的兵｡
‫我们知道我们可以把这个受控的兵投到我们的射手角色实现中｡
‫那么我们如何从这里得到人工智能控制器呢？
‫我们已经有了行为树组件, 我们知道它在一个AI控制器上｡
‫如果我们转到Yu行为树组件, 看看这里有没有什么有用的方法, 也许我们可以使用它｡
‫这里有很多,
‫但是如果我们寻找控制器, 我们可能只在它的某个基类中看到任何东西, 因为YU行为树组件的父类是Yu大脑组件｡
‫我们继续查那个然后在这里找控制器｡
‫你可以看到它的属性｡
‫有吸气剂吗？
‫是的, 有一个名为get AI owner的函数, 如果我们将鼠标悬停在它上面, 它应该会返回一个AI控制器指针｡
‫所以你应该可以用它来控制卒, 把它投给一个射手角色, 然后调用shoot方法｡
‫所以这将是你的挑战调用shoot方法, 使它公开, 获得卒, 投卒,
‫调用, shoot, 然后在你的行为树中测试它｡
‫暂停视频, 开始体验｡
‫好吧, 我会的
‫欢迎回来｡
‫首先, 第一步是我们要把这个shoot方法设为公共的因为它需要从这个类的外部调用.
‫所以我会把它仅仅承担损害｡
‫我们会拍摄, 给予它一点空间, 一点呼吸的空间｡
‫我喜欢白色能帮我看东西｡
‫帮我想想｡
‫然后我们要去BT任务拍摄｡
‫我们首先要检查控制器是否为空｡
‫否则我们就不能在上面使用箭头运算符｡
‫只是一般的, 做这些空值检查的好习惯｡
‫所以如果这个AI的所有者不等于, 抱歉等于空指针, 我们会希望提前返回一个失败｡
‫如果没有人工智能控制器, 这个任务就会失败｡
‫这很简单
‫所以我将返回ET节点结果冒号｡
‫结肠就这样失败了｡
‫然后我们将创建所有者组件, 获得AI所有者, 我们将对其进行处理｡
‫实际上, 我们可能需要在这里包含一个头文件｡
‫让我们做一个哈希包含, 它将是游戏框架和控制器｡
‫事实上, 我认为, 是的, 任何控制器都可以,
‫但我认为我们需要人工智能控制器, 因为这是我们要返回的指针类型, 然后我们要做一个箭头,
‫我们要做一个获取典当, 在这里抱怨我的文件头中的东西｡
‫也许我有些地方做得不对｡
‫所以正斜杠我看起来像我弄错了｡
‫它实际上不在游戏框架中｡
‫你只需要一个控制器就可以了｡
‫教教我怎么对这件事这么无动于衷｡
‫好了, 我们走吧｡
‫我们现在可以从棋子中取出棋子了｡
‫就像我说的, 我们还需要做一个演员阵容｡
‫所以我们要对射手角色的A进行类型转换.
‫这就是完整的射手角色, 射手角色.
‫我们还需要检查结果｡
‫但我们需要把枪手的角色也包括进去｡
‫所以哈希包括在顶部的射手字符｡
‫托德·H
‫就像这样, 我们要把它存储在一个指针类型的射手角色里｡
‫星星将成为我们的角色｡
‫我们就这么称呼它吧｡
‫我们会把它存放在那里｡
‫基本上我们需要确保如果眼睛当前没有控制兵, get--return because
‫get-—可能返回null｡
‫或者, 如果类型对控制不同类型的——的字符没有问题, 则此强制转换可能返回null｡
‫幸运的是, 这两个指针可以很好地结合在一起, 所以如果你尝试转换一个空指针, 结果就是一个空指针,
‫这就是为什么我们可以这样做｡
‫这些支票都在一行｡
‫然后我们可以做一个if字符｡
‫等于空指针｡
‫那我们又要失败了｡
‫所以返回｡
‫ET节点结果｡
‫结肠｡
‫结肠就这样失败了｡
‫最后, 在所有这些检查之后, 我们知道我们已经有了一个射手角色,
‫我们应该可以调用shoot, so, character, arrow, 然后像这样射击, 这样我们就可以射击了｡
‫让我们转到行为树｡
‫在这里, 我们将下拉以放置一个新节点, 并查找新的拍摄任务｡
‫我不确定我是否编译了, 所以我只是要确保所有的东西都能再次编译｡
‫一旦完成了, 我们就可以过去按播放键, 看看这个家伙是否会上来投篮｡
‫是的, 他知道｡
‫不幸的是, 他不停地开枪, 搬起石头砸自己的脚｡
‫所以有些东西不太对劲｡
‫所以有两件事出了问题｡
‫首先, 他成功地用两枪杀死了自己, 而且看起来他每一帧都在拍摄, 这是有意义的,
‫因为我们看到了球员, 我们走向他们, 然后拍摄是我们在这里的最后一个动作,
‫我们将反复执行｡
‫所以我们要做的是把它变成一个序列｡
‫我将在这里拖出一个名为“创建序列节点”的节点｡
‫我们要做的就是射击, 然后等待, 然后射击, 然后等待, 无限重复｡
‫所以先开枪, 再等等｡
‫也许我们可以等, 我不知道, 在两次拍摄之间等1/2的时间, 然后我们想重复这个过程, 我们可以用装饰器来做｡
‫因此, 如果我右键单击add decorator并查找循环装饰器, 那么您可以看到您希望它循环多少次｡
‫上面写了三次｡
‫我们不想要三次｡
‫我们希望它基本上是无限循环的, 直到我们需要移动或者我们需要看不见玩家, 我们需要去调查｡
‫我们将点击播放, 看看是否有效｡
‫走到我面前｡
‫射门射门射门｡
‫但他并没有真的打我｡
‫你可以看到他的镜头实际上是落在他自己身上｡
‫我们会在下一节课中讨论这个问题｡
‫到时候见｡