前言
在 Unity官方实例教程 Space Shooter(四) 中,我们学会了:
如何让障碍向下移动
如何随机生成障碍
如何生成无尽波数的障碍
如何回收爆炸效果
从现在的游戏功能来看,我们已经具备了基本的玩法了,但是总觉得少了什么,少了什么呢?游戏是无声的,这样怎么能够体现我们太空射击的激烈呢?所以我们接下来给我游戏添加一些惊心动魄的音乐,让玩家一开始就能感受到宇宙的宏伟气势!
你将学到什么?
如何添加游戏背景音乐
如何添加游戏音效
如何调整各个音效之间的平衡
如何给飞船击碎障碍后进行计分
如何判断游戏结束
如何重新开始游戏
如何发布游戏
一、添加背景音乐
在Unity中,要添加背景音乐其实是一件很简单的事情,我们只需要将我们的音频文件挂载一个GameObject上,然后做一些设置就可以让其播放了,对于游戏的背景音乐,我们可以新建一个空的GameObject来进行挂载,但是在本例中,我们直接将音乐挂载在GameController对象上面是非常合适的,所以我们直接来试试看,首先我们在Assets->Audio文件夹中找到我们的背景音乐music_background,然后将其直接拖入GameController对象
然后我们再选中GameController对象,便可以在Inspector视窗中看到音频相关的组件了,如下图:
其中我们需要关注的两个设置:
Play On Awake:这个勾选后,就意味着GameObject对象一生成,音效文件就会开始播放
Loop:这个勾选后,就意味这音效文件会循环播放
对于我们的背景音乐,这两个选项我们都有确保勾选,做完这些,我运行游戏便可以听到宏伟的背景音乐了!
二、添加游戏音效
添加游戏音效的方法和添加游戏背景音乐的方法很类似,在本例中我们会添加3个音效
障碍爆炸音效
飞船爆炸音效
子弹射击音效
首先我们来看前面2个爆炸音效,这两个音效实现非常简单,我们找到爆炸效果的Prefab文件,然后直接将音效文件拖入Prefab中,在这边,我们为了方便拖动,将Project视图改为One Column Layout模式
然后在Assets->Audio文件夹中找到对应的两个音效文件explosion_asteroid和explosion_player,并分别将两个音效文件拖入explosion_asteroid和explosion_player两个Prefab
然后确保Play On Awake模式是勾选的,做完这些,运行一下游戏,便可听到爆炸的音效了
还剩下一个子弹设计的音效,他的挂载方式和上面的都一样,只是播放的方式是需要在代码中激活的,我们首先在Assets->Audio文件夹中找到射击音效weapon_player,然后将音效文件拖入Player对象
然后去掉Play On Awake的勾选,因为我们不能在游戏一开始就播放射击音效,我们需要在发射子弹的时候才会播放,所以我们打开PlayerController脚本,进行编辑:
我们在射击功能的代码中,增加红线标记的语句,这个是5.2的新写法,简单来说就是获取对象的AudioSource组件来调用播放功能
写完代码,保存一下,然后回到Unity编辑器,运行游戏,发射子弹时便可以可以听到子弹射击音效了
三、调节音效平衡
现在我们有了背景音乐,爆炸音效和子弹射击的音效,如果耳朵敏感的朋友,可能会觉得,相对于爆炸音效,子弹射击的音效有些过于大了,所以我们可以通过单独调节射击音效的音量,来到达各个音效之间的一个平衡,首先我们选中Player对象,然后在其AudioSource组件中调整Volume选项,在本例中,我们将Volume调节为0.5
然后我们在运行一下,现在各个音效就处于一个比较平衡的状态了
四、给游戏计分
现在我们的游戏有了玩法,有了声音,已经可以玩乐了,如果增加一个计分功能,就能让玩家有更好的追求,也让重复的射击动作变得有意义,要实现计分功能,我们首先需要一个UI来显示分数,下面我们就来创建一个计分UI,首先我们新建一个Text类型的GameObject,然后将其命名为Score Text,在5.2版本中,新建一个UI类的GameObject,编辑器会自动帮我们创建Canvas和EventSystem两个GameObject
为了让我们的UI适配我们设定的尺寸,所以我需要选中Canvas来修改UI缩放模式,在本例中,我们使用Scale With Screen Size模式,也就根据屏幕尺寸来缩放,然后将引用的屏幕分辨率设置为600*900,也就是我们的游戏屏幕尺寸
然后选中Score Text,修改它的位置,使其处于屏幕合适的位置,在本例中,我们将它的x和y值分别设置为-205和420,让其处于屏幕的左上角
有了这个计分UI后,我们需要思考一下,如何才能让它正确显示玩家的分数呢?
首先我们得有一个变量来记录玩家的分数
然后我们需要有一个方法,来实现当分数发生变化是通知UI更新分数
接着我们需要在障碍被子弹击碎时增加一定分数
那么我们就来看看如何实现上面的内容,要实现上面内容的第一点和第二点,比较合理的方式是在我的GameController里面来实现,所以我们打开GameController脚本,增加以下代码:
首先我们引入了UnityEngine.UI的库文件,因为我们下面会需要在代码中定义Text类型的变量,而Text类型的变量属于UnityEngine.UI的内容,所以我们需要在开头进行引入,这样程序才能识别Text类型的变量
然后我们定义了一个私有变量score,来记录玩家的分数,因为我们不希望这个变量可以手动设置,所以设置为私有类型的
接着我们定义一个公共变量scoreText,用来设置显示分数的UI对象
然后我们在游戏开始时,将score设置为0,接着调用UpdateScore方法来更新分数UI
接着我们来看看UpdateScore方法的具体内容,非常简单,就是修改scoreText的文本内容,文本内容由两部分组成,Score:固定文字加上score变量数值
最后我们定义一个公共的方法addScore,之所以是公共的,因为我会在其他的脚本中调用,所以需要将其设置为public类型,函数里面我们就只有两句话,将现在的分数加上增加的分数,然后再更新分数
写完代码,保存一下,然后回到Unity编辑器,将我们的Score Text对象拖入到scoreText变量中
做完这些,我们就实现了第一点和第二点的内容了,那么第三点我们该如何实现呢?我怎么实现子弹击碎障碍的时候来增加分数呢?我们先回忆一下,子弹击碎障碍的逻辑代码在哪个脚本里面?没错就是DestroyByContact,所以打开它然后新增以下代码:
首先我们定义一个公共变量score,来设置每个障碍的击碎后的得分
然后我定义一个私有变量gameController,因为我们需要通过调用GameController脚本中的addScore方法来增加分数
接着我们在Start方法中,需要获取GameController的实例,这里我们的步骤是,首先找到GameController的GameObject,然后在通过GetComponent方法来获取GameController脚本的实例
这里面有两个if语句,第一个if是表示当我们获取的GameController对象不为空时,我才通过GetComponent方法来获取GameController脚本的实例
第二个if是表示当我们获取的GameController对象是空的时候,我们输出Debug信息,告诉我们脚本没有找到
最后我们在障碍被击碎的逻辑里面,调用GameController的addScore方法来增加分数
写完代码,保存一下,然后回到Unity编辑器,将score设置为10(这个数值你可以根据自己喜好来设置,但建议最好大于0),然后运行游戏,这时你会发现每次你击碎障碍后,分数就会增加10分
五、是时候结束游戏啦
现在我们的游戏越发完美了,但是还存在一个挺严重的问题,就是游戏无法结束,即使我们的飞船被炸毁,游戏也不会结束,这可不太好,所以我们需要设置一下,当我们的飞船被炸毁后,我们就结束游戏!
相信有些聪明的朋友,已经想到了制作思路——我们在判断飞船炸毁的脚本里面,添加一句让游戏结束的代码就行了,没错,其实思路就是这么简单,接下来我们来看看怎么实现:
添加GameOver的UI
首先我们还是新建一个Text对象,然后命名为GameOver Text,然后修改它的显示内容为GameOver,为了让他更加醒目,我们将他的字体调整为25,然后位置摆放在屏幕的中间,并且修改它的文本对象方式为中心对象,接着将其字体颜色设置为红色,具体属性设置如下图:
然后你变会看到游戏屏幕中间就会有一个大大的红色的GameOver了,接着我们需要修改GameController脚本来让程序知道如何判断游戏结束
首先我们定义一个公共变量gameOverText,用来设置显示GameOver的UI对象
然后我们定义一个私有的变量,用来保存游戏是否结束的标志,它是Bool类型的变量,只有true和false两种情况
接着我们在游戏开始,将gameOverText的文字内容设置为空,因为一开始游戏肯定还没有结束,所以我们不能让玩家看到gameOverText
同时一开始我们也需要将gameOver标记为false,即游戏还未结束
然后我们定义一个公共方法GameOver,来实现游戏结束时的逻辑处理,在这个方法中,我们做了两件事情,一是将gameOver标记为true,然后将gameOverText的文字内容设置为“GameOver”
写完代码,保存一下,然后回到Unity编辑器,将我们的GameOver Text对象拖入到gameOverText变量中
接着我们再打开DestroyByContact脚本,进行如下编辑:
我们在飞机撞毁的逻辑中,调用GameOver方法来通知GameController来结束游戏
写完代码,保存一下,然后回到Unity编辑器,运行游戏,测试一下,你会发现当飞船被撞毁后,游戏就会出现GameOver的提示了
六、有结束就有重新开始
现在我们游戏可以结束了,但是如果游戏结束之后,我们不能重新开始,那游戏岂不是只能玩一次,所以我们需要给游戏增加重新开始的功能,为了让玩家知道怎么来重新开始,所以我们需要新建一个Text来提示玩家如何来重新开始,我们将新建的Text命名为Restart Text,然后将其的属性设置为下图所示:
然后我们打开GameController脚本来控制重新开始的逻辑:
首先我们定义一个公共变量restartText,来设置显示重新开始信息的UI对象
然后我们定义一个私有变量restart,来标记游戏是否处于重新开始状态
接着我们在游戏开始的时候,将restartText的文本内容设置为空,因为一开始不需要显示任何信息,同时将restart标记为false
然后我们在Update方法中进行检测,如果游戏处于重新开始状态下,并且玩家按下了R键,我们就重新加载当前场景(即重新开始游戏)
最后我们在障碍生成的循环中,进行检测,如果游戏处于GameOver状态,我们就将restart标记为true,同时将restartText的文本内容设置为“Press 'R' to Restart”
写完代码,保存一下,回到Unity编辑器,然后将Restart Text拖入restartText,接着运行游戏,测试一下
七、最后一步——发布游戏
终于,我们的游戏制作已经完成了,接下来就是发布游戏,可以分享给我们的朋友玩啦,关于如何发布游戏在 Unity官方实例教程 Roll-a-Ball(二 )的最后我们有讲解过,所以这里就不做详细介绍啦,希望每个读者朋友都能真正学以致用,而不是依赖教程,最后谢谢所有能够看到这里的朋友!