﻿1
00:00:04,290 --> 00:00:05,340
‫你好, 欢迎｡

2
00:00:05,340 --> 00:00:11,610
‫这节课, 我们将用C++实现一个shoot节点, 让我们的敌人变得更有威胁｡

3
00:00:11,610 --> 00:00:13,800
‫让我们一起来看看怎么做吧｡

4
00:00:14,580 --> 00:00:19,980
‫所以我们的行为树中明显缺少的一项功能就是射击的能力｡

5
00:00:19,980 --> 00:00:24,930
‫我最理想的做法是移动到玩家的位置, 然后开枪｡

6
00:00:24,930 --> 00:00:28,560
‫但我们想先稍微改变一下我们的运动方式｡

7
00:00:28,560 --> 00:00:34,290
‫我需要调整几个方面, 如果选择“移动到节点”, 则需要更改的一个方面是半径｡

8
00:00:34,290 --> 00:00:39,990
‫我不想让敌人直接靠近我, 所以如果我改变可接受的半径,

9
00:00:39,990 --> 00:00:42,930
‫那么它将在离我五米远的地方停止移动｡

10
00:00:42,930 --> 00:00:43,740
‫所以它会停止｡

11
00:00:43,740 --> 00:00:45,690
‫给予我五米的距离｡

12
00:00:45,690 --> 00:00:46,650
‫他朝我走过来, 就这样｡

13
00:00:46,650 --> 00:00:48,180
‫他停下来盯着我｡

14
00:00:48,180 --> 00:00:54,780
‫现在我想做的另一件事是在黑板部分, 你可以看到有一个观察到的黑板值｡

15
00:00:54,780 --> 00:00:58,470
‫如果我们没有检查, 让我们看看我移动时会发生什么｡

16
00:00:58,500 --> 00:01:03,660
‫他基本上, 这是稍微更明显, 当我们有一个较小的可接受的半径｡

17
00:01:03,660 --> 00:01:06,780
‫所以我们现在把它降到54｡

18
00:01:06,990 --> 00:01:09,840
‫如果我点击播放, 那么你可以看到我的移动｡

19
00:01:09,840 --> 00:01:14,940
‫他去了我的最后一个位置, 然后他只有当他到达那里, 他来更新｡

20
00:01:14,940 --> 00:01:16,320
‫这不是我们想要的

21
00:01:16,320 --> 00:01:19,530
‫我们想要的是它不断地向我们走来｡

22
00:01:19,530 --> 00:01:25,320
‫如果你检查观察黑板值, 那么它的意思就是每次玩家位置改变,

23
00:01:25,320 --> 00:01:30,180
‫我们都会更新我们的移动位置.

24
00:01:30,180 --> 00:01:37,770
‫所以如果我点击播放和移动, 你可以看到他一直在跟着我, 更新他的路径｡

25
00:01:37,770 --> 00:01:39,180
‫这正是我们想要的｡

26
00:01:39,180 --> 00:01:43,830
‫现在我们可以将接受半径更改为500, 这样就不那么明显了｡

27
00:01:43,830 --> 00:01:47,250
‫但是我们仍然可以观察到黑板上的值｡

28
00:01:47,250 --> 00:01:54,330
‫然后我们想要的行为是一旦他进入我们的半径范围内, 就像这样, 他会停下来向我们开枪｡

29
00:01:54,330 --> 00:01:56,730
‫为此, 我们需要一种新的任务｡

30
00:01:56,730 --> 00:01:58,950
‫所以我们要在这里创建一个新的C++任务｡

31
00:01:58,950 --> 00:02:02,100
‫所以我们要添加一个新的C++类｡

32
00:02:02,100 --> 00:02:06,990
‫然后我们将显示所有类并查找节拍任务｡

33
00:02:07,020 --> 00:02:12,030
‫现在, 我们需要哪一个, 节拍任务节点还是节拍任务黑板库？

34
00:02:12,030 --> 00:02:16,500
‫其实我们并不需要用钥匙因为我们只要试着开枪就行了.

35
00:02:16,500 --> 00:02:17,520
‫这就是我们要做的｡

36
00:02:17,520 --> 00:02:23,520
‫我们要扣动扳机, 否则瞄准将在行为树的其他地方完成｡

37
00:02:23,610 --> 00:02:31,650
‫我们打开task节点, 这里是基类, 我们将把它命名为beat task.

38
00:02:32,420 --> 00:02:33,320
‫下划线｡

39
00:02:33,350 --> 00:02:34,190
‫开枪啊

40
00:02:34,760 --> 00:02:36,700
‫让我们继续创建该类｡

41
00:02:36,710 --> 00:02:39,470
‫然后我们就得到了这样的结果｡

42
00:02:39,470 --> 00:02:41,960
‫所以我们要做同样的设置｡

43
00:02:41,960 --> 00:02:47,690
‫因此, 对你们来说, 有一个小小的挑战, 就是做同样的设置, 就像我们的黑板一样,

44
00:02:47,690 --> 00:02:48,920
‫清晰的黑板值｡

45
00:02:48,920 --> 00:02:52,220
‫我们希望有一个名称, 我们希望有一个执行任务｡

46
00:02:52,220 --> 00:02:54,020
‫现在假设视频并尝试一下｡

47
00:02:54,050 --> 00:02:54,920
‫好的欢迎回来｡

48
00:02:54,920 --> 00:02:56,480
‫所以这是一个小任务｡

49
00:02:56,480 --> 00:03:04,610
‫我只需要把签名从一个干净的黑板上复制过来, 包括公共和受保护的部分｡

50
00:03:04,610 --> 00:03:07,640
‫我将更改构造函数的名称｡

51
00:03:07,640 --> 00:03:10,130
‫我将继续执行并实现我们的构造函数｡

52
00:03:10,130 --> 00:03:12,050
‫我们需要做什么？

53
00:03:12,080 --> 00:03:16,490
‫我们需要将节点名称设置为shoot｡

54
00:03:16,490 --> 00:03:17,690
‫我们就这么称呼它｡

55
00:03:17,690 --> 00:03:25,820
‫然后回到shoot任务的header, 我们现在要尝试实现execute任务, 我们只需要调用super｡

56
00:03:25,820 --> 00:03:32,600
‫我将从clear blackboard值CP文件中复制该值, 然后我们就可以开始实施了｡

57
00:03:32,600 --> 00:03:39,860
‫首先我们要做的是, 让我们有更多的空间我们要抓住棋子.

58
00:03:39,860 --> 00:03:41,540
‫我们为什么要抓到我们的棋子？

59
00:03:41,540 --> 00:03:45,020
‫好吧, 让我们来看看射手角色, 它是一个棋子｡

60
00:03:45,020 --> 00:03:46,580
‫还记得那个枪手吗

61
00:03:46,580 --> 00:03:48,890
‫点H有一个拍摄方法｡

62
00:03:48,890 --> 00:03:54,770
‫这就是我们想要称之为“我们”的东西, 本质上和玩家所做的一样｡

63
00:03:54,770 --> 00:03:58,460
‫他按住了扳机按钮, 这就是射击方法.

64
00:03:58,460 --> 00:04:01,100
‫我们希望人工智能也能这样做｡

65
00:04:01,100 --> 00:04:06,830
‫当你有射击任务时, 它会按住触发按钮或反复按下该触发按钮,

66
00:04:06,830 --> 00:04:10,070
‫这样执行任务就可以完成这项任务｡

67
00:04:10,100 --> 00:04:15,260
‫我们可能会返回这里的值, 因为记住, 这个动作只有一次｡

68
00:04:15,260 --> 00:04:16,760
‫这不是连续射击｡

69
00:04:16,760 --> 00:04:17,570
‫我们该怎么办？

70
00:04:17,600 --> 00:04:22,430
‫如果我们或成功, 我们将返回ET节点结果成功｡

71
00:04:22,430 --> 00:04:28,430
‫如果我们成功了, 因为我们不需要不断地冷静滴答｡

72
00:04:28,430 --> 00:04:32,630
‫我们不需要此任务运行超过一帧的时间｡

73
00:04:32,630 --> 00:04:36,950
‫我们需要做的另一件事是, 就像我说的, 掌握典当类｡

74
00:04:36,950 --> 00:04:41,330
‫我接下来要做的是向你们展示如何使用人工智能控制器｡

75
00:04:41,330 --> 00:04:47,540
‫从AI控制器中, 我们知道我们可以调用get pawn来获取被控制的兵｡

76
00:04:47,540 --> 00:04:53,570
‫我们知道我们可以把这个受控的兵投到我们的射手角色实现中｡

77
00:04:53,570 --> 00:04:58,850
‫那么我们如何从这里得到人工智能控制器呢？

78
00:04:58,850 --> 00:05:03,560
‫我们已经有了行为树组件, 我们知道它在一个AI控制器上｡

79
00:05:03,560 --> 00:05:12,350
‫如果我们转到Yu行为树组件, 看看这里有没有什么有用的方法, 也许我们可以使用它｡

80
00:05:12,350 --> 00:05:18,140
‫这里有很多,

81
00:05:18,140 --> 00:05:24,560
‫但是如果我们寻找控制器, 我们可能只在它的某个基类中看到任何东西, 因为YU行为树组件的父类是Yu大脑组件｡

82
00:05:24,560 --> 00:05:27,350
‫我们继续查那个然后在这里找控制器｡

83
00:05:27,350 --> 00:05:29,420
‫你可以看到它的属性｡

84
00:05:29,450 --> 00:05:31,100
‫有吸气剂吗？

85
00:05:31,100 --> 00:05:38,840
‫是的, 有一个名为get AI owner的函数, 如果我们将鼠标悬停在它上面, 它应该会返回一个AI控制器指针｡

86
00:05:38,840 --> 00:05:46,370
‫所以你应该可以用它来控制卒, 把它投给一个射手角色, 然后调用shoot方法｡

87
00:05:46,370 --> 00:05:51,740
‫所以这将是你的挑战调用shoot方法, 使它公开, 获得卒, 投卒,

88
00:05:51,740 --> 00:05:56,480
‫调用, shoot, 然后在你的行为树中测试它｡

89
00:05:56,480 --> 00:05:57,890
‫暂停视频, 开始体验｡

90
00:05:57,980 --> 00:05:58,280
‫好吧, 我会的

91
00:05:58,280 --> 00:05:58,880
‫欢迎回来｡

92
00:05:58,880 --> 00:06:07,280
‫首先, 第一步是我们要把这个shoot方法设为公共的因为它需要从这个类的外部调用.

93
00:06:07,280 --> 00:06:09,200
‫所以我会把它仅仅承担损害｡

94
00:06:09,200 --> 00:06:12,200
‫我们会拍摄, 给予它一点空间, 一点呼吸的空间｡

95
00:06:12,200 --> 00:06:13,670
‫我喜欢白色能帮我看东西｡

96
00:06:13,700 --> 00:06:14,540
‫帮我想想｡

97
00:06:14,540 --> 00:06:17,240
‫然后我们要去BT任务拍摄｡

98
00:06:17,240 --> 00:06:21,500
‫我们首先要检查控制器是否为空｡

99
00:06:21,500 --> 00:06:24,380
‫否则我们就不能在上面使用箭头运算符｡

100
00:06:24,380 --> 00:06:27,140
‫只是一般的, 做这些空值检查的好习惯｡

101
00:06:27,140 --> 00:06:35,420
‫所以如果这个AI的所有者不等于, 抱歉等于空指针, 我们会希望提前返回一个失败｡

102
00:06:35,420 --> 00:06:38,570
‫如果没有人工智能控制器, 这个任务就会失败｡

103
00:06:38,570 --> 00:06:39,920
‫这很简单

104
00:06:39,920 --> 00:06:43,730
‫所以我将返回ET节点结果冒号｡

105
00:06:43,730 --> 00:06:45,590
‫结肠就这样失败了｡

106
00:06:45,590 --> 00:06:52,580
‫然后我们将创建所有者组件, 获得AI所有者, 我们将对其进行处理｡

107
00:06:52,580 --> 00:06:54,680
‫实际上, 我们可能需要在这里包含一个头文件｡

108
00:06:54,680 --> 00:07:02,240
‫让我们做一个哈希包含, 它将是游戏框架和控制器｡

109
00:07:02,240 --> 00:07:08,240
‫事实上, 我认为, 是的, 任何控制器都可以,

110
00:07:08,240 --> 00:07:13,250
‫但我认为我们需要人工智能控制器, 因为这是我们要返回的指针类型, 然后我们要做一个箭头,

111
00:07:13,250 --> 00:07:16,850
‫我们要做一个获取典当, 在这里抱怨我的文件头中的东西｡

112
00:07:16,850 --> 00:07:18,620
‫也许我有些地方做得不对｡

113
00:07:18,620 --> 00:07:21,440
‫所以正斜杠我看起来像我弄错了｡

114
00:07:21,440 --> 00:07:23,000
‫它实际上不在游戏框架中｡

115
00:07:23,000 --> 00:07:26,300
‫你只需要一个控制器就可以了｡

116
00:07:26,300 --> 00:07:28,640
‫教教我怎么对这件事这么无动于衷｡

117
00:07:28,640 --> 00:07:29,180
‫好了, 我们走吧｡

118
00:07:29,180 --> 00:07:31,040
‫我们现在可以从棋子中取出棋子了｡

119
00:07:32,100 --> 00:07:34,890
‫就像我说的, 我们还需要做一个演员阵容｡

120
00:07:34,890 --> 00:07:41,610
‫所以我们要对射手角色的A进行类型转换.

121
00:07:41,610 --> 00:07:45,780
‫这就是完整的射手角色, 射手角色.

122
00:07:45,780 --> 00:07:48,990
‫我们还需要检查结果｡

123
00:07:48,990 --> 00:07:51,360
‫但我们需要把枪手的角色也包括进去｡

124
00:07:51,360 --> 00:07:55,650
‫所以哈希包括在顶部的射手字符｡

125
00:07:56,040 --> 00:07:57,000
‫托德·H

126
00:07:57,570 --> 00:08:02,100
‫就像这样, 我们要把它存储在一个指针类型的射手角色里｡

127
00:08:02,100 --> 00:08:04,440
‫星星将成为我们的角色｡

128
00:08:04,650 --> 00:08:05,430
‫我们就这么称呼它吧｡

129
00:08:05,430 --> 00:08:06,510
‫我们会把它存放在那里｡

130
00:08:06,870 --> 00:08:14,070
‫基本上我们需要确保如果眼睛当前没有控制兵, get--return because

131
00:08:14,070 --> 00:08:17,520
‫get-—可能返回null｡

132
00:08:18,310 --> 00:08:25,810
‫或者, 如果类型对控制不同类型的——的字符没有问题, 则此强制转换可能返回null｡

133
00:08:25,840 --> 00:08:30,640
‫幸运的是, 这两个指针可以很好地结合在一起, 所以如果你尝试转换一个空指针, 结果就是一个空指针,

134
00:08:30,640 --> 00:08:33,040
‫这就是为什么我们可以这样做｡

135
00:08:33,130 --> 00:08:34,870
‫这些支票都在一行｡

136
00:08:35,380 --> 00:08:37,690
‫然后我们可以做一个if字符｡

137
00:08:39,150 --> 00:08:41,250
‫等于空指针｡

138
00:08:42,390 --> 00:08:44,670
‫那我们又要失败了｡

139
00:08:44,670 --> 00:08:45,960
‫所以返回｡

140
00:08:46,990 --> 00:08:49,090
‫ET节点结果｡

141
00:08:49,480 --> 00:08:49,900
‫结肠｡

142
00:08:49,900 --> 00:08:51,910
‫结肠就这样失败了｡

143
00:08:51,910 --> 00:08:56,260
‫最后, 在所有这些检查之后, 我们知道我们已经有了一个射手角色,

144
00:08:56,260 --> 00:09:04,810
‫我们应该可以调用shoot, so, character, arrow, 然后像这样射击, 这样我们就可以射击了｡

145
00:09:04,810 --> 00:09:07,570
‫让我们转到行为树｡

146
00:09:07,840 --> 00:09:16,330
‫在这里, 我们将下拉以放置一个新节点, 并查找新的拍摄任务｡

147
00:09:16,330 --> 00:09:20,680
‫我不确定我是否编译了, 所以我只是要确保所有的东西都能再次编译｡

148
00:09:20,680 --> 00:09:25,870
‫一旦完成了, 我们就可以过去按播放键, 看看这个家伙是否会上来投篮｡

149
00:09:26,560 --> 00:09:27,400
‫是的, 他知道｡

150
00:09:27,400 --> 00:09:32,860
‫不幸的是, 他不停地开枪, 搬起石头砸自己的脚｡

151
00:09:32,860 --> 00:09:35,950
‫所以有些东西不太对劲｡

152
00:09:35,950 --> 00:09:37,900
‫所以有两件事出了问题｡

153
00:09:37,900 --> 00:09:43,330
‫首先, 他成功地用两枪杀死了自己, 而且看起来他每一帧都在拍摄, 这是有意义的,

154
00:09:43,330 --> 00:09:48,160
‫因为我们看到了球员, 我们走向他们, 然后拍摄是我们在这里的最后一个动作,

155
00:09:48,160 --> 00:09:52,210
‫我们将反复执行｡

156
00:09:52,210 --> 00:09:56,350
‫所以我们要做的是把它变成一个序列｡

157
00:09:56,350 --> 00:10:00,280
‫我将在这里拖出一个名为“创建序列节点”的节点｡

158
00:10:00,280 --> 00:10:04,810
‫我们要做的就是射击, 然后等待, 然后射击, 然后等待, 无限重复｡

159
00:10:04,810 --> 00:10:07,690
‫所以先开枪, 再等等｡

160
00:10:07,690 --> 00:10:14,950
‫也许我们可以等, 我不知道, 在两次拍摄之间等1/2的时间, 然后我们想重复这个过程, 我们可以用装饰器来做｡

161
00:10:14,950 --> 00:10:21,490
‫因此, 如果我右键单击add decorator并查找循环装饰器, 那么您可以看到您希望它循环多少次｡

162
00:10:21,520 --> 00:10:22,540
‫上面写了三次｡

163
00:10:22,540 --> 00:10:23,470
‫我们不想要三次｡

164
00:10:23,470 --> 00:10:30,340
‫我们希望它基本上是无限循环的, 直到我们需要移动或者我们需要看不见玩家, 我们需要去调查｡

165
00:10:30,430 --> 00:10:32,970
‫我们将点击播放, 看看是否有效｡

166
00:10:32,990 --> 00:10:33,610
‫走到我面前｡

167
00:10:33,610 --> 00:10:35,890
‫射门射门射门｡

168
00:10:35,890 --> 00:10:37,510
‫但他并没有真的打我｡

169
00:10:37,510 --> 00:10:41,860
‫你可以看到他的镜头实际上是落在他自己身上｡

170
00:10:42,520 --> 00:10:46,660
‫我们会在下一节课中讨论这个问题｡

171
00:10:46,660 --> 00:10:47,380
‫到时候见｡

