﻿1
00:00:04,130 --> 00:00:04,610
‫嘿, 你好

2
00:00:04,610 --> 00:00:05,450
‫欢迎回来｡

3
00:00:05,480 --> 00:00:09,080
‫我们已经创建了一个基类—-C++类｡

4
00:00:09,200 --> 00:00:16,310
‫在本视频中, 我们将从该类派生, 以基于base-—创建一个新子类｡

5
00:00:16,340 --> 00:00:19,310
‫所以让我们来讨论一下为什么我们要这么做｡

6
00:00:19,580 --> 00:00:27,080
‫我们有一个基类, 我们知道我们会有两个不同的类从基类派生出来.

7
00:00:27,080 --> 00:00:30,020
‫我们会有我们的坦克, 我们会有塔｡

8
00:00:30,050 --> 00:00:34,760
‫现在, 底部——包含网格, 一个胶囊以及一个产卵点｡

9
00:00:34,760 --> 00:00:38,210
‫而这些都是坦克和塔都可以继承的东西｡

10
00:00:38,360 --> 00:00:44,480
‫但坦克和塔也将有一些功能, 彼此不同｡

11
00:00:44,480 --> 00:00:50,720
‫首先, 我们的坦克将在世界各地移动, 它也将由玩家控制｡

12
00:00:50,720 --> 00:00:55,220
‫因此, 需要将其配置为从键盘和鼠标接收输入｡

13
00:00:55,220 --> 00:00:57,950
‫而塔, 则是坐在那里｡

14
00:00:57,980 --> 00:01:03,860
‫它不需要玩家的任何输入, 因为它的动作都将由代码控制｡

15
00:01:03,860 --> 00:01:10,010
‫因为坦克和塔的行为不同,

16
00:01:10,010 --> 00:01:18,290
‫我们将利用继承来创建基类的子类——这样我们就可以继承它们的共同点, 然后为每个类添加那些不同的特性｡

17
00:01:18,290 --> 00:01:23,960
‫我们回到了编辑器, 我将进入C++类, TuneTank的文件夹,

18
00:01:23,960 --> 00:01:29,240
‫我们在那里有基类, 这就是我们要从中派生的类.

19
00:01:29,240 --> 00:01:35,480
‫现在, 我们可以右键单击此处并选择“创建从base派生的C++类”——｡

20
00:01:35,480 --> 00:01:43,550
‫让我们选择它, 我将允许它把这个类粘贴到与base相同的源代码, tune tank文件夹中｡

21
00:01:43,610 --> 00:01:47,360
‫至于它的名字, 我就叫它坦克｡

22
00:01:47,360 --> 00:01:55,400
‫所以我们的坦克类将是我们真正的坦克的类——我们在世界上控制和移动｡

23
00:01:55,430 --> 00:01:57,410
‫因此, 让我们单击“创建类”｡

24
00:01:57,560 --> 00:02:06,470
‫好了, 我们已经编译了, vs代码已经打开了, 有了新的坦克文件, 还有坦克CP｡

25
00:02:06,500 --> 00:02:08,210
‫现在这些都是光秃秃的｡

26
00:02:08,210 --> 00:02:15,950
‫这里什么都没有, 虽然我们看不到它们, 但我们从基类继承了一些东西.

27
00:02:15,950 --> 00:02:19,580
‫我们确实有那些添加到基础中的组件——｡

28
00:02:19,580 --> 00:02:23,810
‫即使这些是私有变量, 它们仍然存在于这个类中｡

29
00:02:23,810 --> 00:02:29,030
‫现在我们已经创建了坦克类, 让我们来讨论几件事.

30
00:02:29,030 --> 00:02:31,880
‫坦克需要炮塔不需要｡

31
00:02:31,880 --> 00:02:39,530
‫既然我们要控制坦克, 我们需要一种方法来关注坦克, 因为它在整个关卡中滚动｡

32
00:02:39,950 --> 00:02:43,880
‫在这张照片中, 这是一个摄像头组件｡

33
00:02:43,880 --> 00:02:47,030
‫它的C++类是摄像头组件｡

34
00:02:47,180 --> 00:02:55,100
‫这条红线叫做弹簧臂组件, 它的C++类就是弹簧臂组件.

35
00:02:55,100 --> 00:03:01,370
‫把这些部件加到一个——让我们可以从摄像机的角度来观察——｡

36
00:03:01,370 --> 00:03:08,930
‫如果摄像机和它的弹簧臂以某种方式连接到......, 它们会跟随......在世界各地｡

37
00:03:08,930 --> 00:03:14,540
‫现在, 回到编辑器中, 如果我们返回到——的文件夹并打开BP--tank, 我们可以单击视口,

38
00:03:14,540 --> 00:03:16,730
‫这样我们就可以看到所有内容｡

39
00:03:16,730 --> 00:03:22,100
‫然后, 我们可以选择胶囊组件, 单击添加并选择弹簧臂｡

40
00:03:22,100 --> 00:03:24,080
‫这是一个弹簧臂组件｡

41
00:03:24,080 --> 00:03:25,610
‫它看起来像一条红线｡

42
00:03:25,730 --> 00:03:31,490
‫现在, 选择弹簧臂组件后, 我们可以添加另一个组件并选择相机｡

43
00:03:31,490 --> 00:03:37,400
‫现在, 我们将摄像头连接到弹簧臂上, 一旦我们开始控制,

44
00:03:37,400 --> 00:03:41,230
‫我们就可以从摄像头的角度进行观察了｡

45
00:03:41,240 --> 00:03:43,040
‫现在弹簧臂非常有用｡

46
00:03:43,040 --> 00:03:49,940
‫它有这个目标臂长度, 如果你调整它, 你会看到摄影机随着弹簧臂一起调整｡

47
00:03:49,940 --> 00:03:54,470
‫所以这是一种控制摄像机距离的方法——｡

48
00:03:54,470 --> 00:04:00,170
‫这些肯定是我们需要的, 类, 但我们将从C++端添加它们,

49
00:04:00,170 --> 00:04:04,460
‫而不仅仅是在蓝图中添加.

50
00:04:04,460 --> 00:04:05,750
‫所以我要把它们删掉｡

51
00:04:05,750 --> 00:04:10,130
‫所以作为你们的挑战, 我希望你们能在坦克课上增加一些东西｡

52
00:04:10,130 --> 00:04:16,790
‫首先, 我们需要一个弹簧臂组件和一个摄像头组件, 所以创建这些变量并将它们作为指针｡

53
00:04:16,790 --> 00:04:21,920
‫继续创建一个公共部分和一个私有部分, 并将这些变量放在私有部分中｡

54
00:04:21,920 --> 00:04:27,590
‫现在我们需要这些是U属性, 所以给予它们属性宏, 并根据前面课程中学到的内容,

55
00:04:27,590 --> 00:04:31,610
‫在这些宏中填入适当的说明符｡

56
00:04:31,640 --> 00:04:36,920
‫现在, 一旦你创建了这些变量, 创建一个构造函数,

57
00:04:36,920 --> 00:04:44,120
‫把它放在公共部分, 并在CP文件中定义它, 然后在构造函数中使用create default

58
00:04:44,120 --> 00:04:46,340
‫sub对象构造我们的相机和弹簧臂组件｡

59
00:04:46,340 --> 00:04:50,750
‫请确保使用安装附件将这些组件连接到某个东西上｡

60
00:04:50,750 --> 00:04:54,380
‫我们希望将弹簧臂组件附加到根组件｡

61
00:04:54,380 --> 00:05:00,500
‫因此, 使用根组件并设置安装附件, 对于摄像机, 将其连接到弹簧臂｡

62
00:05:00,500 --> 00:05:02,870
‫您可以指涉回基底类别｡

63
00:05:03,020 --> 00:05:05,950
‫A提醒自己做这些事情的代码是什么样子的｡

64
00:05:05,960 --> 00:05:09,710
‫继续暂停视频并将这些内容添加到坦克类中｡

65
00:05:12,580 --> 00:05:13,180
‫好吧, 我会的

66
00:05:13,180 --> 00:05:14,380
‫所以我们在坦克｡

67
00:05:15,250 --> 00:05:16,540
‫现在, 先说正事｡

68
00:05:16,540 --> 00:05:20,110
‫我想要一个公共区和一个私人区.

69
00:05:20,350 --> 00:05:24,840
‫因此, 我们将在private部分添加这两个新组件｡

70
00:05:24,850 --> 00:05:32,290
‫我们需要一个U形弹簧臂组件, 它是一个指针, 我们可以称之为弹簧臂｡

71
00:05:32,290 --> 00:05:37,760
‫我们还需要一个新的摄像头组件, 我们称之为摄像头｡

72
00:05:37,780 --> 00:05:38,260
‫没关系, 我会的

73
00:05:38,260 --> 00:05:39,970
‫如果你们的名字稍有不同｡

74
00:05:40,090 --> 00:05:46,420
‫现在, 马上, 我在这里看到了IntelliSense错误, 这意味着我需要向前声明这些错误｡

75
00:05:46,420 --> 00:05:51,280
‫所以我要用弹簧臂和摄像头｡

76
00:05:51,280 --> 00:05:53,150
‫现在这些都是正向声明的｡

77
00:05:53,170 --> 00:05:55,240
‫现在我们需要新的房产｡

78
00:05:55,240 --> 00:05:57,460
‫因此, 让我们添加新的属性宏｡

79
00:05:57,970 --> 00:06:02,930
‫在属性宏中, 我们需要一些说明符.

80
00:06:02,950 --> 00:06:09,550
‫这些参数在任何位置都是可见的, 因为我们看到组件需要在任何位置都是可见的,

81
00:06:09,550 --> 00:06:13,010
‫以便我们能够在详细信息面板中调整它们的参数｡

82
00:06:13,030 --> 00:06:18,550
‫现在, 我没有看到任何立即需要暴露到事件图, 所以我认为我们不需要蓝图读取､

83
00:06:18,550 --> 00:06:20,600
‫写入或蓝图只读｡

84
00:06:20,620 --> 00:06:21,160
‫没关系, 我会的

85
00:06:21,160 --> 00:06:23,770
‫如果您添加了它们, 我现在将忽略它们｡

86
00:06:23,770 --> 00:06:25,630
‫我将给予这些分类｡

87
00:06:26,410 --> 00:06:33,330
‫由于这些都是组件, 我将把它们与其他组件沿着放在组件类别中｡

88
00:06:33,340 --> 00:06:38,940
‫现在, 我没有将它们公开给事件图, 所以我不需要在这里指定梅塔allow private access｡

89
00:06:38,950 --> 00:06:45,640
‫这对于弹簧臂来说已经足够了, 我想给予摄像头组件赋予相同的属性｡

90
00:06:46,180 --> 00:06:47,590
‫所以我把它复制过来｡

91
00:06:47,590 --> 00:06:49,270
‫现在我们有了组件｡

92
00:06:49,420 --> 00:06:54,700
‫接下来要做的是在构造函数中构造它们, 这意味着我们需要一个构造函数｡

93
00:06:54,700 --> 00:07:03,910
‫现在构造函数的名字和类的名字一样, 所以它是一个tank, 我们需要在CP文件中定义这个构造函数.

94
00:07:03,910 --> 00:07:08,710
‫所以让我们去坦克指挥所, 并创建一个坦克｡

95
00:07:09,520 --> 00:07:17,710
‫这就是我们的函数体, tank构造函数必须以类名和作用域解析操作符作为前缀｡

96
00:07:17,710 --> 00:07:19,360
‫就是这里的双冒号

97
00:07:19,360 --> 00:07:24,850
‫这样我们就不仅仅是创建了一个新函数, 而是定义了这个类的构造函数｡

98
00:07:24,850 --> 00:07:27,130
‫现在, 我们要构建这些组件｡

99
00:07:27,130 --> 00:07:29,530
‫让我们从弹簧臂开始｡

100
00:07:29,860 --> 00:07:39,160
‫所以我们要说弹簧臂等于创建默认子对象, 这将是一个u弹簧臂组件｡

101
00:07:41,260 --> 00:07:45,310
‫至于文本, 我就简单地称之为弹簧臂｡

102
00:07:46,270 --> 00:07:54,490
‫对于附件, 我们将设置弹簧臂, 设置附件, 传入根组件｡

103
00:07:55,920 --> 00:07:56,220
‫现在就去

104
00:07:56,220 --> 00:07:57,240
‫我一直在等｡

105
00:07:57,240 --> 00:07:58,050
‫就在那儿｡

106
00:07:58,050 --> 00:08:03,920
‫IntelliSense错误指出指向不完整类类型的指针使用了spring arm组件｡

107
00:08:03,930 --> 00:08:10,320
‫这是因为我们需要包含头文件, 因为我们要创建和使用弹簧臂组件｡

108
00:08:10,320 --> 00:08:16,020
‫这是我的虚幻引擎文档, 如果我向下滚动, 这是我的包含｡

109
00:08:16,020 --> 00:08:21,820
‫我将复制并粘贴到顶部, 就在水箱边缘下面.

110
00:08:21,900 --> 00:08:26,520
‫现在, 只是一个侧记, 一般来说, 你要把你的类头文件放在顶部,

111
00:08:26,520 --> 00:08:29,370
‫把你的组件的包含放在下面｡

112
00:08:29,370 --> 00:08:30,750
‫我们有了弹簧臂｡

113
00:08:30,750 --> 00:08:32,790
‫是时候组装摄像机了｡

114
00:08:32,790 --> 00:08:39,300
‫所以我们要说创建默认的子对象, 摄像机组件｡

115
00:08:40,050 --> 00:08:45,240
‫在文本宏中, 我将把它简单地称为相机｡

116
00:08:45,240 --> 00:08:51,120
‫对于相机, 我将调用安装附件, 通过弹簧臂｡

117
00:08:51,390 --> 00:08:54,240
‫当然我需要相机头文件｡

118
00:08:54,240 --> 00:08:59,820
‫这是虚幻引擎文档,

119
00:08:59,820 --> 00:09:05,490
‫这里是搜索文档, 我将输入摄像头组件, 这里是摄像头组件｡

120
00:09:05,490 --> 00:09:06,600
‫我会选择它｡

121
00:09:06,600 --> 00:09:09,450
‫这是摄像头组件的文档｡

122
00:09:09,450 --> 00:09:14,100
‫所以我会把它复制粘贴到文件的顶部｡

123
00:09:14,100 --> 00:09:15,930
‫现在我们应该没事了｡

124
00:09:15,960 --> 00:09:18,630
‫好的, 让我们继续编译这个｡

125
00:09:18,810 --> 00:09:19,230
‫好吧, 我会的

126
00:09:19,230 --> 00:09:21,180
‫所以我有一个成功的编译｡

127
00:09:21,210 --> 00:09:24,210
‫让我们回到编辑器, 然后回到坦克.

128
00:09:24,240 --> 00:09:30,690
‫当然, 我们什么都看不到, 因为tank是从base派生的我们刚添加的组件,

129
00:09:30,690 --> 00:09:33,510
‫我们添加到了tank类中.

130
00:09:33,510 --> 00:09:39,720
‫所以BP--tank不会得到这些, 因为它不是从tank类派生的.

131
00:09:39,720 --> 00:09:46,710
‫现在, 我们可以根据坦克类创建一个新的蓝图, 但之后我们必须重新设置这些组件｡

132
00:09:46,710 --> 00:09:50,190
‫我真的不想再经历一次｡

133
00:09:50,190 --> 00:09:55,080
‫我们有一个更简单的方法可以把这个蓝图修复到坦克类｡

134
00:09:55,080 --> 00:10:01,530
‫我们通过转到类设置来实现这一点, 在选中类设置的详细信息面板中, 我们可以看到类选项,

135
00:10:01,530 --> 00:10:04,980
‫其中有一个父类｡

136
00:10:04,980 --> 00:10:10,800
‫下拉列表显示它被设置为base upon, 但是如果我们单击它,

137
00:10:10,800 --> 00:10:13,200
‫我们可以搜索tank并选择tank作为基类｡

138
00:10:13,200 --> 00:10:17,220
‫而现在这个蓝图就是从坦克类衍生出来的｡

139
00:10:17,220 --> 00:10:24,630
‫我们可以看到, 我们为组件设置的所有属性（如网格和胶囊大小）仍然存在｡

140
00:10:24,660 --> 00:10:27,090
‫只是现在我们看到了摄像机｡

141
00:10:27,390 --> 00:10:29,730
‫事实上, 我们有一个弹簧臂和一个摄像头｡

142
00:10:29,730 --> 00:10:33,720
‫如果我们现在选择弹簧臂, 我们可以看到那条红线｡

143
00:10:33,720 --> 00:10:34,710
‫所以这是伟大的｡

144
00:10:34,710 --> 00:10:38,880
‫因此, 我可以使用此弹簧臂组件并更改其目标臂长度｡

145
00:10:38,880 --> 00:10:46,650
‫如果我喜欢, 我可以把它设置为600, 我甚至可以改变它的旋转,

146
00:10:46,650 --> 00:10:52,770
‫使它的角度相机在坦克下选择旋转模式和旋转了一点｡

147
00:10:52,770 --> 00:10:58,500
‫就像, 所以现在我想指出的是, 你不应该改变摄像机的位置｡

148
00:10:58,530 --> 00:11:05,190
‫选择摄影机并将其在世界上四处移动, 以便正确定位和调整角度, 这可能很有吸引力｡

149
00:11:05,190 --> 00:11:07,350
‫但这不是正确的做法｡

150
00:11:07,350 --> 00:11:13,410
‫正确的方法是设置弹簧臂零部件的旋转和目标臂长度｡

151
00:11:13,410 --> 00:11:17,790
‫原因是你想把摄像机连接到弹簧臂的末端｡

152
00:11:17,790 --> 00:11:23,460
‫弹簧臂有很多不同的内置功能,

153
00:11:23,460 --> 00:11:29,430
‫如当相机撞到墙上以避开障碍物时收缩, 挡住池塘的视线等｡

154
00:11:29,430 --> 00:11:35,070
‫所以你要把摄像机连接到弹簧臂的末端, 然后调整弹簧臂,

155
00:11:35,070 --> 00:11:39,990
‫而不是调整摄像机的位置和旋转｡

156
00:11:40,110 --> 00:11:47,070
‫因此, 在本视频中, 我们创建了tank类, 并从base pond派生, 以继承base

157
00:11:47,070 --> 00:11:48,960
‫pond类的这些特性｡

158
00:11:49,140 --> 00:11:56,100
‫我们添加了一个弹簧臂组件和一个摄像头组件, 并使用visible only将它们暴露给编辑器,

159
00:11:56,100 --> 00:11:58,500
‫并将它们放在各自的类别中｡

160
00:11:58,500 --> 00:12:05,130
‫所以我们一步一步的接近成品, 我们会在下一节课继续开发这个水箱｡

161
00:12:05,460 --> 00:12:06,510
‫我很快就会见到你的｡

