【GAD翻译馆】VR100天教程:第六天Survival Shooter教程II
今天在第六天中,我们将完成Survival Shooter教程剩下的部分,最后继续开发一个我自己的简单游戏!
今天,我们学习更多关于:
1)创建用户界面(UI)
2)玩家和敌人开发攻击和移动功能
3)光线投射(Raycasting)
4)创造更多的动画
所以让我们开始吧!
Health HUD
在视频系列的下一部分中,我们为游戏创建了敌人攻击我们的时候的health UI。
创建Canvas 父对象
我们要做的第一件事是在hierarchy面板上创建一个新的Canvas对象。我们命名为HUDCanvas
我们在Canvas对象上添加一个Canvas Group组件。根据文档,我们在Canvas Group中检测的任何内容都将持续到其子对象中。
特别的,我们希望取消对Interactable的检查,并阻塞Raycast。我们希望避免UI做这些事情。
添加Health UI容器
接下来,我们在我们的HUDCanvas上创建一个空的游戏对象。这将是我们的Health UI的父容器。我们把它命名为HealthUI。
有趣的是,因为它是Canvas对象的子对象,我们也有一个与我们的游戏对象附加的RectTransform组件。
点击RectTransform组件,把我们的HealthUI放到游戏的左下角。记住按住alt + shift键移动锚点和位置
添加Health图片
接下来,我们在HealthUI上创建一个Image UI。在图像(脚本)组件中,我们只需要附加提供的Heart.png图像
你应该在我们的场景选项卡中看到这样的东西:
在我们的游戏选项卡中应该是这样的:
创建UI滑块(Slider)
接下来,我们需要创建HP bar,他是用来表示玩家拥有的血量HP。
我们通过在画布上创建一个Slider UI GameObject来实现这一点。滑块(Slider)作为canvas对象的子对象。删除除了填充区域的其他内容,。
接下来我们要做的是制作HP。在滑块(Slider)游戏对象中,使最大值为100,设置默认值也为100。
注意:如果无法让滑块完全符合视频开始时的样子。可以切换到滑动条的RectTransform组件,来准确的定位。
当玩家被击中时,添加一个屏幕闪烁
接下来,我们创建了一个名为DamageImage的Image UI,它是HUDCanvas的子对象。
我们想让它填满整个canvas对象。这可以通过进行RectTransform组件,点击定位框,然后在按住alt + shift时点击拉伸宽度和高度按钮来完成。
我们也想让颜色不透明。我们可以通过单击color并将A(alpha)值移动到0来实现。
当你完成所有事情时,你的画布应该是这样的。
玩家的生命值(Health)
我们将已经创建的PlayerHealth脚本附加到玩家的GameObject对象上。
这是代码:
像以前一样,视频注释掉了一些代码,因为我们还没有达到那个点。
需要注意的是,函数是如何被分隔成模块的,这些模块指定了所有的内容,而不是把所有的内容都放进Update ()中。
从我们的脚本中可以看到一些东西:
看下Update ()函数
在Update ()函数中我们创建了受伤后的屏幕闪烁动画效果。
如果玩家受到伤害(damaged的布尔值变为true),我们将DamageImage设置为红色,然后我们更改布尔值为false。
然后,当我们继续在每一个帧上调用Update()时,我们将创建一个lerp,它将帮助我们从受伤害的颜色过渡到原始的颜色。
实现伤害功能
我们如何将damaged的值设置为true?从TakeDamage()函数中!
注意公有函数:
public void TakeDamage (int amount)
我们在之前的教程中已经见过这个了。正如你所记得的那样,这意味着每当我们访问脚本组件时,我们就可以调用这个函数。
将组件附加到脚本上
代码的其余部分已经有了很好的注释文档,因此我将把它留给你来自行阅读。
在继续之前,我们必须将组件附加到脚本中。
创建敌人攻击脚本
前面提到过,我们有一个public TakeDamage()函数,它允许其他脚本调用。问题是,哪个脚本调用它?
答案是:敌人攻击脚本。已经为我们提供了,只要把它附在玩家对象上。
代码看起来是这样的:
和以前一样,有些东西代码没有注释,这个函数的基本原理是:
敌人靠近玩家,导致OnTriggerEnter()被激活,我们将playerInRange布尔值设置为true。
在我们的Update()函数中,如果要在敌人的范围内进行攻击,我们调用Attack ()函数,如果玩家仍然活着,则调用TakeDamage()函数来减少血量。
之后,如果玩家HP的值为0或者比零还小,那么我们就触发来让玩家死亡的动画。
否则,如果超过僵尸没有发生碰撞,OnTriggerExit()将被调用,playerInRange将被设置为false,不会有攻击状态。
我们所有的游戏功能,或者至少在某种意义上,我们只能逃跑,或者被敌人杀害。
注意:如果怪物没有追到你,请确保你将Playerobject与玩家标记连接在一起,否则脚本将无法找到玩家对象。
伤害敌人功能
在之前的视频中,我们让敌人追捕并杀死了玩家。我们目前没有办法反击。
我们将在下一段视频中给敌人设定HP值来解决这个问题。我们可以通过将敌人的EnemyHealth 脚本附加到敌人的游戏对象上。
脚本内容如下:
在某种程度上,这与我们所拥有的PlayerHealth脚本非常相似。
最大的区别是当玩家死亡时,游戏结束,然而当敌人死去时,我们需要以某种方式让他们离开游戏。
这个脚本的流程是这样的:
我们在Awake ()初始化脚本
当敌人通过我们的公有函数:TakeDamage()而受到伤害时,我们将使用特殊效果,以显示敌人受到伤害,并调整我们的health变量。
如果敌人的HP小于或等于0时,我们调用死亡函数,触发死亡动画和其他死亡相关的代码。
我们调用StartSinking (),它将把isSinking的布尔值设为true。
你可能会注意到,StartSinking ()在任何地方都没有调用。这是因为当我们的敌人动画结束播放它的死亡片段时作为一个事件被调用。你可以在Zombunny动画中发现它。
在isSinking被设置为true后,我们的Update()函数将开始将敌人移出。
移动到玩家
我们的敌人现在有HP了。接下来我们要做的就是让我们的玩家角色可以正常伤害敌人。
我们需要做的第一件事是一些特殊的效果。
我们需要复制粒子组件在GunParticles预制
然后把它传递到GunBarrelEnd(player对象的子对象)游戏对象上
接下来,还在GunBarrelEnd中添加一个行渲染组件。用来画一条线,这将是我们的子弹。
对于材料,我们使用为我们提供的LineRendereredMaterial。
我们还将组件的宽度设为0.05,这样我们发射的线看起来就像你在其他游戏中看到的小型突击步枪。
确保禁用渲染器,因为我们不想在加载时立即显示它。
接下来,我们需要添加一个光照组件。我们把它设成黄色。
接下来,我们将玩家射击作为我们枪的音频源。
最后,我们附上了我们开枪的脚本。这里是:
脚本的流程是:
Awake ()函数初始化我们的变量
在Update ()函数中,我们等待用户左键点击,然后调用shoot()
在Shoot()中,我们创建一个Raycast,它将一直向前走,直到它遇到敌人或结构,或者达到我们所设定的最大距离。从那里,我们从枪到我们击中的点创建我们的LineRenderer。
在Update ()几帧之后,我们将禁用LineRenderer,以产生我们正在向外发射一些东西的错觉。
在这一点上,我们必须做一些清理工作。我们必须回到EnemyMovement脚本,注释掉那些阻止敌人移动的代码,当玩家或者它死亡的时候。
着重提出的变化是:
在完成所有这些之后,我们就有了一个可以玩的游戏!
注意:如果你开始玩游戏,试着向敌人射击,什么也没有发生。检查敌人的图层是否设置为Shootable。
得分
现在我们有了一个完整的游戏!下一步是什么呢?你可以从下一个视频中猜出,我们正在建立一个分数系统。
我们最后做了一些类似于之前的两个视频教程所做的事情,我们在屏幕上放置了一个UI文本。
锚点
既然如此,我们在HUDCanvas中创建一个UI文本。我们将RectTransform设置为顶部。这一次,我们希望通过单击而不按住shift键来设置锚点。
字体
接下来,在文本(Text)组件中,我们希望将字体(Font)样式更改为LuckiestGuy,这是为我们提供的字体资产
添加阴影效果
接下来,我们将阴影部分添加到文本中,给它一个很酷的小阴影。我用了一些值来让它看起来很漂亮。
添加ScoreManager
最后,我们需要添加一个脚本,以追踪我们的分数。为了做到这一点,我们必须创建一个ScoreManager脚本,如下代码所示:
这段代码非常简单。我们有一个score变量,在Unity中,每次Update ()调用时显示得分。
那么分数会在哪里更新呢?它不会在ScoreManager中,它会在我们的敌人死亡的时候出现。具体到我们的EnemyHealth脚本。
这是它!现在,我们可以得到的总分为1。但是下个视频中我们会增加敌人。
创建一个预制
在我们继续下一个视频之前,我们做了一个敌人的预制。就像我们在之前的视频中看到的,prefabs可以被描述为一个现有的游戏对象的模板。
他们方便做相同的多个副本,如多个敌人!
产生
在这个即将到来的视频中,我们学习了如何创建多个可以追逐玩家的敌人。
要做的第一件事就是创造出僵尸。
可重复使用,如果你有类似的动画像zombear和Zombunny敌人的模型,你可以重复使用相同的动画。
然而,我无法看到任何动画剪辑Zombear所以,我决定跳过这一部分。
在那一刻,我陷入了一种完全的懒惰,并决定跳过这一阶段。
然而,一些重要的事情需要注意的是,如果我们有模型有相同类型的动画,但不同的模型,我们可以创建一个AnimatorOverrideController,接受一个AnimtorController使用相同的动画剪辑。
EnemyManager
之后我们,简单尝试添加多种类型的敌人,我们必须创建一个方法来产生一个敌人。
为此,我们创建一个空对象,在hierarchy面板中命名为EnemyManager。
然后我们附加我们的EnemyManager脚本,提供给我们:
这段代码的流程是:
在Start()中,我们调用InvokeRepeating来调用“Spawn”方法。
在Spawn ()函数中,我们将从产生点的数组中随机创建一个敌人。然而,在这种情况下,我们只有一个位置。它被放入数组中用于可重用的目的。
但在我们继续之前,我们必须创建产生点。
我们创建了一个新的空对象:Zombunny产生点,我设置为:
位置:(-20.5,0,12.5)
旋转:(0 130 0)
然后从那里,只要拖动“僵尸”的产生点到敌人管理脚本内的spawnPoint标签,就可以将游戏对象添加到我们的数组中。
如果我们完全地跟随视频教程,我们将会有多个产生点,很难区分它们之间的区别。
Unity对此有一个答案。
我们创建添加一个标签,点击在你的游戏对象的inspector面板中的有色方块(colored cube),并选择一个颜色。
玩这个游戏,现在你应该看到一波无休止的僵尸来攻击你!现在我们已经接近完整的游戏了!
游戏结束
在本教程的最后一个视频中,我们为玩家创建了一个更流畅的游戏。
目前,当玩家死亡时,所有的事情都是我们重新加载游戏,玩家重新开始。我们将会做得更好,并添加一些漂亮的UI效果!
我们要做的第一件事就是创建一个Image UI,我们叫它screenFader。我们将图像的颜色设为黑色, alpha为0。稍后我们将创建一个转换来改变图像的Alpha,这样我们就会在游戏中逐渐消失。
接下来,我们创建了一个名为GameOverText的Text UI,向玩家展示游戏已经结束。
在这一点上,我们必须确保在我们的HUDCanvas中有这样的顺序:
1)HealthUI
2)DamageImage
3)ScreenFader
4)GameOverText
5)ScoreText
我们有这样的顺序是很重要的,因为列表中的顶部元素将首先被放置在屏幕上。
如果我们把所有东西堆叠在一起,我们的HealthUI就会在底部,而ScoreText会在顶部。
创建一个动画
现在我们已经有了所有的UI元素,我们想创建一个UI动画。
我们需要做的第一件事是去 Unity > Window > Animation选择HUDCanvas ,使用附加到HUDCanvas上的对象创建一个新的动画。
点击创建一个新剪辑并制作一个名为GameOverClip的新剪辑。
单击添加属性并选择:
GameOverText > Rect Transform > Scale
GameOverText > Text > Color
ScoreText > Rect Transform > Scale
ScreenFader > Image > Color
这将为我们的动画添加这4个属性。
当你双击效果的时间轴时,你可以为属性创建一个菱形。
当你将白线滑块移动到菱形,并选择它时,你可以更改inspector面板中的属性值,游戏对象将在动画中指定的时间内进行。
从本质上来说,动画将从第一个菱形逐渐转变为第二个菱形。或者从最初的位置到菱形。
一个例子是:在0:00,如果X的刻度是1,在0:20 X刻度是2,在0:10,X刻度是1.5
所以请按照上面的图片做的。
GameOverText:Scale,我们想要创建一个弹出式的文本,文本在那里消失,然后弹出。
0:00 Scales都是1
0:20 Scales都是0
0:30 Scales都是1
GameOverText: Text.Color,我们想要创造白色的文字逐渐淡出。
0:00 color值为白色,alpha值为0
0:30 color值为白色,alpha值为255
ScoreText: Scale,我们想要分数比例缩小一点
0:00 scales都是1
0:30 scales都是0.8
ScreenFader: Image.Color,我们逐渐让黑色背景出现
0:00 color值是黑色,alpha值为0
0:30 color值是黑色,alpha值为255
当我们创建一个动画时,Unity已经为我们创建动画控制器(Animator Controller)
设置我们的HudCanvas Animator Controller(动画控制器)
在HudCanvas Animator Controller(动画控制器)中,我们创建两个新状态。
一个将作为一个主要的过渡,另一个将会使游戏结束。
我们还创建了一个叫做GameOver的新触发器。
我们使 New State 作为主要过渡。从那里我们创建一个 New State到GameOver的过渡,当触发游戏被启用时这个过程被调用。
在你做完之后,我们应该有这样的东西:
保存我们的工作,然后我们就基本完成了!
注意:当我们从HUDCanvas创建动画时,它会添加animator controller(动画控制器)。如果没有,手动创建一个Animator组件到HUDCanvas并连接HUDCanvas的animator controller(动画控制器)。
创建一个游戏管理器来使用我们的动画。
最后,在最后一步中,我们需要创建一些代码,当游戏结束时,这些代码将使用我们刚刚创建的动画。要做到这一点,我们只需将提供的GameOverManager脚本添加到我们的HUDCanvas。代码如下:
代码的基本流程是:
在Awake()函数中我们通过抓取连接到我们的游戏对象的Animator组件来初始化动画器(Animator),我们将一直检查玩家是否还活着,如果玩家死亡,我们将会播放GameOver动画,并设置一个定时器,所以死亡动画播放之后游戏会被重置,重新开始。
总结
这已经过去2天了。
我决定坚持到底的原因是:
当你必须写代码时候,会有很多好的学习方式。
很有可能这将是最后一篇基础教程文章了。从现在开始,我将会自己去创建一个简单的游戏,当我试图为我的答案尝试谷歌时,进度会慢得多。
下面我们看回顾一下知识点,虽然很多都是我们学到的东西。
1)用户界面系统
2)对撞机
3)Raycasts
4)Unity导航
然后我们看到更多的东西我们从来没有见过的:
1)角色模型动画
2)控制游戏状态的管理脚本
3)创建我们自己的UI动画
4)在Unity中使用人工智能
这是我们虚拟现实100天教程的第六天。
我将在第7天看到你,在那里我会尝试开发我自己的简单游戏。
访问VR挑战100天 的内容表
【版权声明】
已经询问原文作者,并获取原文作者翻译许可,译文获得授权。
联系原文作者JoshChang