美文网首页unity官方教程合集游戏编程研究院Unity3D
Unity官方实例教程 Space Shooter(五)

Unity官方实例教程 Space Shooter(五)

作者: Zui | 来源:发表于2015-11-17 23:08 被阅读15066次
Space Shooter 太空射击

传送门

Unity官方实例教程 Space Shooter(一)
Unity官方实例教程 Space Shooter(二)
Unity官方实例教程 Space Shooter(三)
Unity官方实例教程 Space Shooter(四)
Unity官方实例教程 Space Shooter(五)

前言

游戏截图

Unity官方实例教程 Space Shooter(四)中,我们学会了:

  • 如何让障碍向下移动
  • 如何随机生成障碍
  • 如何生成无尽波数的障碍
  • 如何回收爆炸效果

从现在的游戏功能来看,我们已经具备了基本的玩法了,但是总觉得少了什么,少了什么呢?游戏是无声的,这样怎么能够体现我们太空射击的激烈呢?所以我们接下来给我游戏添加一些惊心动魄的音乐,让玩家一开始就能感受到宇宙的宏伟气势!

你将学到什么?

  • 如何添加游戏背景音乐
  • 如何添加游戏音效
  • 如何调整各个音效之间的平衡
  • 如何给飞船击碎障碍后进行计分
  • 如何判断游戏结束
  • 如何重新开始游戏
  • 如何发布游戏

一、添加背景音乐

在Unity中,要添加背景音乐其实是一件很简单的事情,我们只需要将我们的音频文件挂载一个GameObject上,然后做一些设置就可以让其播放了,对于游戏的背景音乐,我们可以新建一个空的GameObject来进行挂载,但是在本例中,我们直接将音乐挂载在GameController对象上面是非常合适的,所以我们直接来试试看,首先我们在Assets->Audio文件夹中找到我们的背景音乐music_background,然后将其直接拖入GameController对象

将背景音乐拖入**GameController**

然后我们再选中GameController对象,便可以在Inspector视窗中看到音频相关的组件了,如下图:

音频组件

其中我们需要关注的两个设置:

  • Play On Awake:这个勾选后,就意味着GameObject对象一生成,音效文件就会开始播放
  • Loop:这个勾选后,就意味这音效文件会循环播放

对于我们的背景音乐,这两个选项我们都有确保勾选,做完这些,我运行游戏便可以听到宏伟的背景音乐了!

二、添加游戏音效

添加游戏音效的方法和添加游戏背景音乐的方法很类似,在本例中我们会添加3个音效

  • 障碍爆炸音效
  • 飞船爆炸音效
  • 子弹射击音效

首先我们来看前面2个爆炸音效,这两个音效实现非常简单,我们找到爆炸效果的Prefab文件,然后直接将音效文件拖入Prefab中,在这边,我们为了方便拖动,将Project视图改为One Column Layout模式

One Column Layout模式

然后在Assets->Audio文件夹中找到对应的两个音效文件explosion_asteroidexplosion_player,并分别将两个音效文件拖入explosion_asteroidexplosion_player两个Prefab

拖入音效文件

然后确保Play On Awake模式是勾选的,做完这些,运行一下游戏,便可听到爆炸的音效了

还剩下一个子弹设计的音效,他的挂载方式和上面的都一样,只是播放的方式是需要在代码中激活的,我们首先在Assets->Audio文件夹中找到射击音效weapon_player,然后将音效文件拖入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,编辑器会自动帮我们创建CanvasEventSystem两个GameObject

截图

为了让我们的UI适配我们设定的尺寸,所以我需要选中Canvas来修改UI缩放模式,在本例中,我们使用Scale With Screen Size模式,也就根据屏幕尺寸来缩放,然后将引用的屏幕分辨率设置为600*900,也就是我们的游戏屏幕尺寸

UI缩放模式

然后选中Score Text,修改它的位置,使其处于屏幕合适的位置,在本例中,我们将它的x和y值分别设置为-205和420,让其处于屏幕的左上角

左上角的计分UI

有了这个计分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变量中

拖入到**scoreText**变量

做完这些,我们就实现了第一点和第二点的内容了,那么第三点我们该如何实现呢?我怎么实现子弹击碎障碍的时候来增加分数呢?我们先回忆一下,子弹击碎障碍的逻辑代码在哪个脚本里面?没错就是DestroyByContact,所以打开它然后新增以下代码:

完整的代码
  • 首先我们定义一个公共变量score,来设置每个障碍的击碎后的得分
  • 然后我定义一个私有变量gameController,因为我们需要通过调用GameController脚本中的addScore方法来增加分数
  • 接着我们在Start方法中,需要获取GameController的实例,这里我们的步骤是,首先找到GameController的GameObject,然后在通过GetComponent方法来获取GameController脚本的实例
  • 这里面有两个if语句,第一个if是表示当我们获取的GameController对象不为空时,我才通过GetComponent方法来获取GameController脚本的实例
  • 第二个if是表示当我们获取的GameController对象是空的时候,我们输出Debug信息,告诉我们脚本没有找到
  • 最后我们在障碍被击碎的逻辑里面,调用GameControlleraddScore方法来增加分数

写完代码,保存一下,然后回到Unity编辑器,将score设置为10(这个数值你可以根据自己喜好来设置,但建议最好大于0),然后运行游戏,这时你会发现每次你击碎障碍后,分数就会增加10分

五、是时候结束游戏啦

现在我们的游戏越发完美了,但是还存在一个挺严重的问题,就是游戏无法结束,即使我们的飞船被炸毁,游戏也不会结束,这可不太好,所以我们需要设置一下,当我们的飞船被炸毁后,我们就结束游戏!

相信有些聪明的朋友,已经想到了制作思路——我们在判断飞船炸毁的脚本里面,添加一句让游戏结束的代码就行了,没错,其实思路就是这么简单,接下来我们来看看怎么实现:

添加GameOver的UI

首先我们还是新建一个Text对象,然后命名为GameOver Text,然后修改它的显示内容为GameOver,为了让他更加醒目,我们将他的字体调整为25,然后位置摆放在屏幕的中间,并且修改它的文本对象方式为中心对象,接着将其字体颜色设置为红色,具体属性设置如下图:

GameOver的属性设置

然后你变会看到游戏屏幕中间就会有一个大大的红色的GameOver了,接着我们需要修改GameController脚本来让程序知道如何判断游戏结束

完整的代码
  • 首先我们定义一个公共变量gameOverText,用来设置显示GameOver的UI对象
  • 然后我们定义一个私有的变量,用来保存游戏是否结束的标志,它是Bool类型的变量,只有true和false两种情况
  • 接着我们在游戏开始,将gameOverText的文字内容设置为空,因为一开始游戏肯定还没有结束,所以我们不能让玩家看到gameOverText
  • 同时一开始我们也需要将gameOver标记为false,即游戏还未结束
  • 然后我们定义一个公共方法GameOver,来实现游戏结束时的逻辑处理,在这个方法中,我们做了两件事情,一是将gameOver标记为true,然后将gameOverText的文字内容设置为“GameOver”

写完代码,保存一下,然后回到Unity编辑器,将我们的GameOver Text对象拖入到gameOverText变量中

拖入到**gameOverText**

接着我们再打开DestroyByContact脚本,进行如下编辑:

完整的代码
  • 我们在飞机撞毁的逻辑中,调用GameOver方法来通知GameController来结束游戏

写完代码,保存一下,然后回到Unity编辑器,运行游戏,测试一下,你会发现当飞船被撞毁后,游戏就会出现GameOver的提示了

六、有结束就有重新开始

现在我们游戏可以结束了,但是如果游戏结束之后,我们不能重新开始,那游戏岂不是只能玩一次,所以我们需要给游戏增加重新开始的功能,为了让玩家知道怎么来重新开始,所以我们需要新建一个Text来提示玩家如何来重新开始,我们将新建的Text命名为Restart 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(二)的最后我们有讲解过,所以这里就不做详细介绍啦,希望每个读者朋友都能真正学以致用,而不是依赖教程,最后谢谢所有能够看到这里的朋友!

相关文章

网友评论

  • 7662ea5ee1bd:在DestroyContact里总说说gameController.addScore (score);这一句没有设置实例对象怎么整
    06937e70433a:@大王从不撩妹 同问,我也这样😩
  • yesufan:感谢教程,可以快速入门
  • b70d8c2ca2e1:请问为什么我发布的时候分辨率不是600*900呀
  • fb4a9f710537:GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    这句代码有什么意义?是获取对象的意思? 获取对象之后呢?
    b70d8c2ca2e1:可以获取对象上的组件
  • bcd8d0db7133:为什么我拖陨石和飞船的爆炸音效进入没有用而是在hierachy里新建了两个陨石爆炸和飞船爆炸?
    a177f79b7d92:@阿辉2017 兄弟 知道原因了么 ? 是因为有地方没有设置好嘛?
    a177f79b7d92:@ilgsh 老哥 知道是啥原因不 我也是这样😟
    阿辉2017:我的也是这样,不解.
  • 53178f3ece17:博主望更新其它教程~~~~
  • en_young:请问大神,为什么restart后,子弹的射程会变很短。。。
  • 69d3ba660a4b:而且呀 碰撞判断放在 DestroyByContact OnTriggerEnter里面处理 当前敌人只有陨石的时候还好 如果有敌机 这代码就不太方便了吧
  • 69d3ba660a4b:我只有一点觉得奇怪
    为什么 if (gameOver)
    {
    restart = true;
    restartText.text = " press R to restart";
    }
    这个代码 要写在SpawnWaves里面判断 很
  • 1b6229d33ed1:补充一点Application.LoadLevel(Application.loadedLevel);重新加载这代码已经弃用了,新版本的可以用SceneManager.LoadScene("Main");代替,Main为你的场景名字,要 using UnityEngine.SceneManagement;
  • 02ce30492cc2:大佬能解释一下最后一步,飞船爆炸后,gameOver和restart都不显示是什么原因吗?
    代码和教程里写得一样。
  • unrpyc:为什么我的计分只加一次就不加了。。。
    31a4877931c0:请问一下问题解决了吗?刚开始是0只有第一次消灭加10,后面都不增加了,一直显示10.
    3cc646f6f80a:同样的问题,求解!
    607723ff9e89:我也遇到了,我打印了一下addScore(int value)里面加的数value就第一次=10,其他的时候都为0,我把加的这个值直接在GameController里定义了
  • 轩辕小羽:感谢教程 期待你讲解别的项目
  • 杨世玲:看完了几篇教程,给你点赞
  • a450c06c9fed:如果有人遇到 按R重新加载游戏 这段代码编译出现“代码已不可用“之类词汇的情况,可以参考下http://forum.china.unity3d.com/thread-13778-1-1.html
  • d57836fb39c0:感谢大神 但是按你的方法做 这个Canvas的位置似乎不太对
    d57836fb39c0:Canvas位置设置不了 一直不在背景上啊
  • Christmas_sd:为什么我用作者给的获取GameController脚本方法不行,
    GameObject.FindWithTag("GameController")
    改成find就可以了:GameObject.Find ("GameController")
    69d3ba660a4b:作者漏写了 要设置GameController的标签 多年编程经验的我一看方法名FindWithTag 就猜到 要设置tag了
    5a2e18a13672:你没有将tag改成GameController,作者代码没有问题
  • acd4c0e6e985:感谢博主教程,请问为什么游戏restart后画面会变暗呢?
    e117da234235:@棠喵 点击Window -> Lighting -> Scene
    取消Auto,点击Build.
    棠喵: @蹬三炮 同问
  • 545bd090c298:感谢教程。
    请问在Build的时候提示
    The type or namespace name `UI' does not exist in the namespace `UnityEngine'. Are you missing an assembly reference?
    是什么情况?
    (可以在游戏里点Play开始,但是不能发布。)

    545bd090c298:@fengz6 错误在GameController.cs的
    using UnityEngine.UI;
  • _Sven:感谢分享。
  • e59a32e63731:博主伟大,两个教程都跟着一步步完成了,求更多教程。
  • 2b2bba035119:你好!我在做到加分的时候一加上gameController.AddScore (score);这句话碰撞就检测就不运行了但是碰撞的时候粒子动画还是播放的 这是什么原因 ?
    963d14e0685a:@棠喵 可是加了GameController 也不行诶
    棠喵: @unityPeople 刚解决了,需要将GameController的tag设为GameController,就ok啦
    棠喵: @unityPeople 我也出现这种情况,请问现在解决了没
  • e3d5825b3de5:博主的教程思路清晰,简洁易懂,非常感谢,希望可以继续做下去,把官方其他教程也讲一下。
  • 记录卡:按照您的教程顺利完成了,很开心。非常感谢!!
  • Zui:看不到你的代码,无法定位问题,可以把计分相关的代码流程自己仔细在过一遍,找找问题所在
  • b8b4057c13e1:请问为什么我按照教程写的但是计分却并不加分。很困惑,希望能得到解答
    69d3ba660a4b:未触发碰撞函数呗 例举一个原因 比如你的rigibody 加在了vnf上 而不是bolt上
    亦或者胶囊盒子没设置对
    e59a32e63731:@lasonbobo 今天也遇到了这个问题,score=10应该加在预设的对象上,而不是一开始创建的。
  • 我女友是小仙女:text怎么设置啊
    e8cb7ddad29d:大魔王你还在吗?我这个canvas太大了,而且就算将他挪到了摄像机下面,他还是没发显示,不知道你当时怎么修改的
    我女友是小仙女:@鱼生生 自己解决了
    我女友是小仙女:@鱼生生 怎么设置他的坐标啊
  • cf4c57d84ba2:博主,请问一下:为什么子弹击中陨石,加分会加双倍?也就是addScore()被调用了两次?
    69d3ba660a4b:应该是子弹销毁触发一次addscore 陨石销毁又触发一次
    也就是说你把子弹有些设置有问题 导致被销毁的时候当成陨石的逻辑来处理了
    Zui:@licongwu 不知道你的代码具体是怎么写的,所以无法给你定位问题所在,提供一个自助的方法,在脚本文件中搜索所有addScore()方法的调用点,然后一个个去理它的逻辑是否合理,哪里重复调用了,就删掉那个地方
  • cf4c57d84ba2:感谢博主的教程,正在努力学习u3d中。想要补充一下:
    想要实现子弹声音,直接将声音文件挂在子弹的prefab上更简单一点。(其实是我的unity版本是5.1不是5.2 :smile:
  • 张自:感谢博主,看完了博主的教材,比看视频清晰明了许多~
  • 一条明:非常支持😁

本文标题:Unity官方实例教程 Space Shooter(五)

本文链接:https://www.haomeiwen.com/subject/ezkkhttx.html