﻿1
00:00:04,460 --> 00:00:05,240
‫你好, 欢迎｡

2
00:00:05,240 --> 00:00:10,250
‫在这节课中,

3
00:00:10,250 --> 00:00:19,940
‫我们将创建一个杀手级的移动的游戏模式, 这只是我们可以创建的游戏模式之一, 因为我们有一个虚拟的—-killed方法, 可以在任何我们想要的游戏模式中调用｡

4
00:00:19,970 --> 00:00:24,560
‫让我们深入了解一下如何实现这个虚方法｡

5
00:00:25,540 --> 00:00:28,640
‫所以我们希望我们的游戏能够结束｡

6
00:00:28,660 --> 00:00:29,760
‫一场比赛结束意味着什么？

7
00:00:29,770 --> 00:00:34,990
‫这意味着我们进入某种状态, 在那里我们是唯一的, 或者我们已经失去了｡

8
00:00:34,990 --> 00:00:37,240
‫我们使用一些UI通知玩家｡

9
00:00:37,270 --> 00:00:40,810
‫我们给予他们重新启动并再次播放的选项｡

10
00:00:41,050 --> 00:00:43,020
‫类似的东西｡

11
00:00:43,030 --> 00:00:46,900
‫现在, 与此相关的类通常是游戏模式｡

12
00:00:46,900 --> 00:00:52,420
‫游戏模式负责决定有关游戏的规则, 例如谁赢谁输｡

13
00:00:52,780 --> 00:00:56,470
‫为此, 我们需要知道谁被杀了｡

14
00:00:56,470 --> 00:01:02,500
‫所以我们这里有一个虚拟方法叫做Pawn Killed,

15
00:01:02,500 --> 00:01:09,370
‫当射手卒死亡时, 它会被调用, 不管是人工智能还是玩家死亡.

16
00:01:10,360 --> 00:01:15,310
‫此外, 我想在这里增加一点复杂性,

17
00:01:15,310 --> 00:01:18,550
‫那就是我们将有不同的游戏模式衍生自我们的主要射击游戏模式｡

18
00:01:18,550 --> 00:01:20,320
‫他们将实施这种游戏模式｡

19
00:01:20,320 --> 00:01:21,580
‫这就是箭头的意思｡

20
00:01:21,580 --> 00:01:25,840
‫箭头的方向通常有点违反直觉, 但把他们都杀了｡

21
00:01:25,840 --> 00:01:35,770
‫游戏模式继承了射击游戏模式, 它覆盖卒杀死, 以计数和决定不同的游戏规则｡

22
00:01:35,770 --> 00:01:41,980
‫所以这就是为什么我想在父射击游戏模式中放置一个虚拟卒杀方法,

23
00:01:42,130 --> 00:01:49,570
‫然后在kill all游戏模式中再次实现或覆盖它, 这将是我们自己实现的游戏模式｡

24
00:01:49,570 --> 00:01:54,490
‫你可能会选择做不同的游戏模式, 也许你只是想杀死一定数量的敌人在水平,

25
00:01:54,490 --> 00:01:58,450
‫而不是所有的他们或沿着这些线的东西｡

26
00:01:58,450 --> 00:02:00,670
‫也许一面夺取的旗帜, 另有一番景象｡

27
00:02:01,900 --> 00:02:08,560
‫但基本上接下来会发生的是射手会找到一个游戏模式, 这个游戏模式就是射手模式,

28
00:02:08,560 --> 00:02:13,060
‫它会称之为被杀.

29
00:02:13,060 --> 00:02:21,250
‫然后根据实际存在的实现, 它将通过重写传递到实现｡

30
00:02:21,910 --> 00:02:28,390
‫现在, 这里的另一个复杂性是,

31
00:02:28,390 --> 00:02:36,310
‫我们的UI逻辑和重启逻辑实际上应该发生在玩家控制器UI中, 通常是玩家的权限, 而不是像游戏模式那样的全局性逻辑｡

32
00:02:36,340 --> 00:02:45,160
‫这在多人游戏中尤其如此, 因为游戏模式实际上并不存在于玩家的机器上, 它只存在于服务器上｡

33
00:02:45,160 --> 00:02:49,270
‫因此, 任何UI的东西都应该在播放器控制器中进行｡

34
00:02:49,540 --> 00:02:52,690
‫这是一个复杂的问题,

35
00:02:52,690 --> 00:02:57,430
‫我们不需要担心, 因为这不是一个多人游戏, 但它仍然是很好的使用类, 因为他们预计将用于虚幻｡

36
00:02:57,880 --> 00:03:04,750
‫播放器控制器, 实际的根播放器控制器类有一个名为game的虚拟方法, 专门用于此目的,

37
00:03:04,750 --> 00:03:12,610
‫以便游戏模式可以调用此方法, 我们可以在自己的射击游戏控制器中实现它, 以执行UI､

38
00:03:12,610 --> 00:03:17,770
‫重新启动等操作｡

39
00:03:17,830 --> 00:03:23,590
‫但是当我们决定游戏结束时, 我们需要从游戏模式中调用它｡

40
00:03:23,590 --> 00:03:28,270
‫所以我们就调用虚拟游戏已经在根玩家控制器上结束了｡

41
00:03:28,390 --> 00:03:35,290
‫然后, 因为根玩家控制器实际上是一个射手, 玩家控制器将结束转移回来, 并调用｡

42
00:03:35,290 --> 00:03:36,130
‫游戏结束了｡

43
00:03:36,130 --> 00:03:42,040
‫因此, 这似乎是一个迂回的路线, 我们将调用从我们的射手兵通过射手游戏模式到杀手更多的游戏模式,

44
00:03:42,040 --> 00:03:46,570
‫到球员控制器, 再到射手球员控制器｡

45
00:03:46,570 --> 00:03:52,360
‫但这给了我们很大的灵活性, 我们可以混合和匹配不同的播放器控制器, 以不同的方式显示UI,

46
00:03:52,360 --> 00:03:55,900
‫在不同的水平｡

47
00:03:55,900 --> 00:04:00,130
‫我们可以混合和匹配不同的游戏模式, 这些模式将以不同的方式工作,

48
00:04:00,130 --> 00:04:02,260
‫这就是我以这种方式构建它的原因｡

49
00:04:02,260 --> 00:04:07,750
‫这对我们的项目来说有点大材小用, 但它向你展示了如何将这一点扩展到其他项目中,

50
00:04:07,750 --> 00:04:11,970
‫包括捕捉旗帜游戏模式和不同种类的玩家控制器｡

51
00:04:11,980 --> 00:04:14,500
‫所以让我们来尝试一下实现它｡

52
00:04:14,530 --> 00:04:18,040
‫我们首先要找到一个路线游戏模式｡

53
00:04:18,040 --> 00:04:22,330
‫因为我是从C++项目开始的, 所以已经创建了一个｡

54
00:04:22,330 --> 00:04:28,120
‫我们有一个简单的射击游戏模式库,

55
00:04:28,120 --> 00:04:37,480
‫我想在这里创建一个公共函数, 它会返回void, 然后它会被杀死, 然后我们要把它传入这里被杀死的.

56
00:04:37,480 --> 00:04:42,400
‫所以这将是一个——一个叫做——被这样杀死的明星｡

57
00:04:42,400 --> 00:04:46,720
‫首先, 我们要把它变成一个虚方法, 然后我们要创建一个基本的实现,

58
00:04:46,720 --> 00:04:50,770
‫它在这里什么都不做.

59
00:04:50,770 --> 00:04:52,930
‫然后我们将创建一个子类｡

60
00:04:52,930 --> 00:05:00,010
‫新的C++类, 会显示所有的类, 我们将寻找我们的射击游戏, 简单的射击游戏模式,

61
00:05:00,010 --> 00:05:02,230
‫作为我们的基类｡

62
00:05:02,230 --> 00:05:12,010
‫我们把这个叫做kill em all游戏模式, 就像这样然后创建这个类.

63
00:05:12,010 --> 00:05:18,100
‫编译完成后, 我想切换到我们的射击游戏角色.

64
00:05:18,130 --> 00:05:23,620
‫你可以看到这里我们有一个死亡的方法｡

65
00:05:23,830 --> 00:05:31,180
‫如果这是死的, 我想做的就是控制游戏模式, 然后叫它"死".

66
00:05:31,210 --> 00:05:38,470
‫我们这样做的方法是, 首先调用get world, 以获取游戏模式,

67
00:05:38,470 --> 00:05:40,690
‫然后获取auth游戏模式.

68
00:05:40,690 --> 00:05:46,750
‫然后我们要做的是这个游戏模式是正确的类型, 这是简单的, 根一个,

69
00:05:46,750 --> 00:05:52,150
‫简单的射击游戏模式, 让我们然后切换出这个字符, 使用它与不同的游戏模式,

70
00:05:52,150 --> 00:05:54,910
‫如捕捉国旗游戏模式｡

71
00:05:55,060 --> 00:06:01,540
‫我们可以这样做, 我们可以在这里的“获取所有游戏”模式中使用尖括号, 我们将做一个简单的射击游戏模式,

72
00:06:01,540 --> 00:06:07,900
‫我们需要在顶部包括它｡

73
00:06:08,320 --> 00:06:15,270
‫所以哈希包括简单的射击游戏模式基地去｡

74
00:06:15,550 --> 00:06:18,070
‫所以我没有完全把整个类名弄对？

75
00:06:18,070 --> 00:06:18,700
‫我想是的｡

76
00:06:18,700 --> 00:06:22,180
‫这将是一个简单的射击游戏模式基地｡

77
00:06:22,360 --> 00:06:23,710
‫这就是我们想要的｡

78
00:06:24,130 --> 00:06:29,290
‫我们可以把它存储在一个变量指针中, 我们称之为游戏模式｡

79
00:06:29,290 --> 00:06:36,790
‫然后我们要做的是在这新的一行, 我们可能要检查我们已经得到了它, 它不是一个空指针｡

80
00:06:36,790 --> 00:06:40,630
‫所以游戏模式不等于空指针｡

81
00:06:40,630 --> 00:06:50,590
‫然后如果它不等于一个空指针, 那就是我们要调用的游戏模式箭头卒杀和卒杀是这样的吗？

82
00:06:50,590 --> 00:06:55,150
‫所以现在游戏模式知道一个兵已经被杀了｡

83
00:06:55,170 --> 00:07:00,460
‫小迷你挑战, 为您覆盖杀死他们所有的游戏模式, 使您可以｡

84
00:07:00,580 --> 00:07:06,880
‫当——被杀死后注销, 并将其设置为地图中的默认游戏模式｡

85
00:07:07,210 --> 00:07:09,680
‫所以希望你有一个小小的挑战｡

86
00:07:09,700 --> 00:07:11,800
‫我们将继续实施｡

87
00:07:11,800 --> 00:07:19,540
‫所以我将通过复制我们简单的射击游戏模式库的公共部分来完成这一点, 很难跟踪所有这些事情｡

88
00:07:19,540 --> 00:07:24,070
‫然后我们要去我们的杀死他们所有的游戏模式基地, 这是继承自它｡

89
00:07:24,310 --> 00:07:33,850
‫我们将粘贴虚方法, 并添加override关键字, 以确保我们正确地覆盖了这个方法.

90
00:07:34,730 --> 00:07:39,620
‫然后, 我将在C++中为KML游戏模式库创建一个实现｡

91
00:07:40,100 --> 00:07:42,980
‫这就是我们应该得到日志消息的地方｡

92
00:07:42,980 --> 00:07:48,430
‫要特别小心, 我们知道在实现中什么都没有, 但你永远不会知道｡

93
00:07:48,440 --> 00:07:52,130
‫以后情况可能会有变化, 我们可能会被炸弹咬到｡

94
00:07:52,140 --> 00:07:55,250
‫所以我们要做一个被杀的棋子｡

95
00:07:56,310 --> 00:07:59,160
‫超级——被杀——被杀｡

96
00:07:59,190 --> 00:08:00,060
‫有道理｡

97
00:08:00,330 --> 00:08:09,630
‫然后我们想做一个你在这里登录基本上说, 一个——被杀了, 我们可以看看是否工作,

98
00:08:09,630 --> 00:08:17,940
‫通过进入虚幻和编译, 然后进入工具栏上的蓝图项目, 并选择在项目设置,

99
00:08:17,940 --> 00:08:23,250
‫我们想成为默认的游戏模式｡

100
00:08:23,250 --> 00:08:29,040
‫如果我们选择游戏模式, 基类, 我们希望它是基于KML的游戏模式｡

101
00:08:29,040 --> 00:08:31,770
‫基本上, 你就去做吧｡

102
00:08:31,770 --> 00:08:35,640
‫事实上, 如果我们去选择, 这并不是我们想要做的｡

103
00:08:35,640 --> 00:08:45,060
‫我们希望它实际上是一个蓝图的孩子, 我们已经有了一个蓝图的孩子, 有很多东西设置｡

104
00:08:45,060 --> 00:08:47,820
‫所以让我们来做一个再教育的工作｡

105
00:08:48,390 --> 00:08:54,090
‫我们会找到根源, 我们会找到BP射击游戏模式, 我们已经在这里｡

106
00:08:54,240 --> 00:09:02,790
‫我们将重命名此BP, kill em all游戏模式,

107
00:09:02,790 --> 00:09:11,940
‫然后我们可以打开它, 停靠窗口, 打开完整的蓝图编辑器, 转到类设置, 并将父级更改为KML游戏模式, 基本上是C++｡

108
00:09:12,030 --> 00:09:18,030
‫这样, 我们应该运行正确的代码, 如果我们去我们的消息,

109
00:09:18,030 --> 00:09:25,740
‫我们的输出日志, 并点击播放, 然后杀死了一个字符, 我们有一个问题, 似乎没有正确的设置｡

110
00:09:25,740 --> 00:09:36,900
‫所以如果我们回到我们的类默认值, 把默认的——类改为BP射手角色, 那应该是正确的｡

111
00:09:36,900 --> 00:09:39,330
‫保存并编译, 以防出错｡

112
00:09:39,330 --> 00:09:42,000
‫然后看看我的蓝图｡

113
00:09:42,000 --> 00:09:44,700
‫它选择了KML游戏模式, C++模式｡

114
00:09:44,700 --> 00:09:49,530
‫因此, 我们实际上要在这里选择一个蓝图, 然后单击播放｡

115
00:09:49,530 --> 00:09:50,850
‫现在我们有了棋子｡

116
00:09:50,850 --> 00:09:57,330
‫我们可以继续杀了这个家伙, 你可以看到一个兵被杀是打印的日志消息｡

117
00:09:57,330 --> 00:10:00,090
‫所以这是非常有效的｡

118
00:10:00,240 --> 00:10:05,580
‫在下一节课中,

119
00:10:05,580 --> 00:10:12,870
‫我们会讲第二部分, 当我们真的想结束博弈并重新开始的时候, 我们就称之为博弈结束.

120
00:10:12,960 --> 00:10:15,930
‫我会在那节课上见到你的｡

