文章目录
- 前言
- 得分
- 暂停
- GameOver!
- 菜单
- 游戏音乐和音效
- 设置界面
前言
[Unity]《太空射击》开发日记Ep.2(初级篇) 麻雀虽小五脏俱全,一个再简陋的游戏也不能少了界面设计。也就是得分,菜单,设置等等,这些功能让游戏成为了一个可控的完整系统。
得分
游戏里要显示一个坚持的时间作为得分,类似Score:xx.xx
Unity中使用一个叫Canvas的对象来管理所有的UI,也就是界面对象。Canvas渲染后会覆盖到游戏画面上,但不会干预游戏的进行,就像加了层滤膜一样。
Canvas会在我们创建UI控件时自动出现,于是我们先创建一个txtScore。
在Hierarchy窗口中,右键UI>Text
,重命名为txtScore。
然后要分两大块处理:
第一块,UI在场景中的位置。双击txtScore之后就会定位到它的位置,你会发现除了X,Y的箭头外,还有一个四叶草一样的东西,这是锚点,是定位相对位置所用的。比如我放置的分数在左上角,我会把锚点也拖到左上角去。
第二块,UI的属性设置。你会发现我已经改好了文本内容和颜色,其实想想也知道是在Inspector窗口改的,具体点的话,我更改了Text和Color两个属性。
现在直接运行,就能看到新添加的文本框了。
如何让分数随着时间递增呢
因为分数只与时间有关,所以分数变化还是很简单的。关键在于如何去修改txtScore的text属性。
我们新建脚本scoreUiController
,附着在txtScore上:
using UnityEngine.UI;
public class scoreUiContrioller : MonoBehaviour {
private float time = 0;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
time += Time.deltaTime;
int score = (int)(time * 1000);
this.GetComponent<Text>().text = "Score:" + score;
}
}
代码说明:
1.using UnityEngine.UI 必须要,不然无法访问UI控件。
2.this指的是脚本附着的游戏对象,GetComponent则是获取附着在this上的所有组件,这里去获取了Text组件,因为这个组件里面保存着分数的文本属性,是我们要修改的东西。
等等等等,这分数加的是爽了,但主角死了这分数也停不下来呀
其实你会发现,所有我们写的脚本都继承自一个MonoBehavior的类,这个类有个自带的继承属性就是enabled,表示启用或禁用。
所以我们只要想方设法获取到txtScore上的scoreUiController
组件并直接禁用他,加分的特效就会消失了。
于是我们回到使主角消失的脚本playerTrigger
,修改成:
public class playerTrigger : MonoBehaviour {
public GameObject scoreUi;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.gameObject.tag=="Enemy")
{
Destroy(other.gameObject);
Destroy(gameObject);
scoreUi.GetComponent<scoreUiContrioller>().enabled = false;
}
}
}
别忘记在Unity里把txtScore赋值给scoreUi属性哦。
最后的效果非常理想:
暂停
接下来要做一个暂停功能,按下’P’暂停,再按下’P’恢复就行
就目前这个游戏的规模来讲,暂停游戏可以直接用Time.timeScale=0实现。
新建脚本gameController
,附着在Main Camera上:
public class gameController : MonoBehaviour {
private bool paused = false;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyUp(KeyCode.P))
{
paused = !paused;
}
if (paused) Time.timeScale = 0;
else Time.timeScale = 1;
}
}
代码说明:
1.paused=!paused,就是让暂停从否变成是,从是变成否。
GameOver!
GameOver!主角被消灭后总要有这样的提示,顺便还要有一个随时按’R’重新开始的功能
先从“重玩”功能开始,这个也非常容易实现,只要重新加载当前场景就可以了。
还是在gameController
脚本里操作:
using UnityEngine.SceneManagement;
public class gameController : MonoBehaviour {
private bool paused = false;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyUp(KeyCode.P))
{
paused = !paused;
}
if (paused) Time.timeScale = 0;
else Time.timeScale = 1;
if(Input.GetKeyUp(KeyCode.R))
{
paused = false;
SceneManager.LoadScene("SampleScene");
}
}
}
代码说明:
1.using UnityEngine.SceneManagement 必须要,不然无法识别场景管理器。
2.SceneManager.LoadScene(“SampleScene”)简单易懂,就是加载指定的场景SampleScene。
至于GameOver!字样,也用UI text来实现就可以,这里就涉及到如何隐藏和显示控件的问题了。
我们先创建一个像模像样的font color=“SlateBlue”>txtGameOver出来:
注意我额外设置了文字水平垂直居中,锚点也是默认中心位置。
接下来我的设想是,开始时该文本enabled=false
,游戏结束时该文本enabled=true
。
因此playerTrigger
完整的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class playerTrigger : MonoBehaviour {
public GameObject scoreUi;
public GameObject gameoverUi;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.gameObject.tag=="Enemy")
{
Destroy(other.gameObject);
Destroy(gameObject);
scoreUi.GetComponent<scoreUiContrioller>().enabled = false;
gameoverUi.GetComponent<Text>().enabled = true;
}
}
}
别忘记在Unity里把txtGameOver赋值给scoreUi属性哦。
菜单
进入游戏之后,应该由玩家自行决定开始游戏和退出游戏。所以我们是需要一个游戏菜单的。
比较适宜的方法是建立一个新的场景作为主菜单,这样“开始游戏”就能干脆地从主菜单场景跳转到游戏场景。这就需要在Scenes
文件夹中新建场景startScene
(在Project窗口中,右键Create>Scene
),顺便把我们的游戏场景名改成gameScene
。
(这里涉及到前面的一个loadScene(),务必记得回去修改一下)
之后在新场景中创建“开始游戏”“退出游戏”两个按钮,在hierarchy窗口中,右键Create>UI>Button
来创建btnGameStart和btnGameExit。从Button的组件里看到,有一个On Click的事件列表:
这个已经充分说明了按钮的点击事件是通过加载一个GameObject的脚本的函数来实现的。所以我们新建一个管理所有按钮点击事件的空对象onClickObject,并附着上新脚本startSceneOnClick
:
using UnityEngine.SceneManagement;
public class startSceneOnClick : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void onStartGame(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
public void onExitGame()
{
Application.Quit();
}
}
之后回到btnGameStart,对这个按钮的点击事件进行设置。
这边有好几步:
1.Runtime Only
改为Editor And Runtime
2.将onClickObject拖入"None"
3.No Function
改为startSceneOnClick.onStartGame
4.在出现的小方框中输入gameScene
“退出游戏“按钮也同理。
到此,一个拥有基本功能的菜单就完成了。
游戏音乐和音效
终于可以开始添加游戏声音了,从按钮的点击音效(SFX)开始吧
音效添加因为是一个比较常用的功能,因此Unity有现成的方法。
1.在需要添加音频的按钮上右键Audio>Audio Source
,重命名为sfxClick。
2.项目文件里新建Sound
文件夹,把你的音效文件sfx.mp3
拖进去。
3.把sfx.mp3
拖到Audio Source下的AudioClip里 ,并且把Play On Awake的√去除。
4.回到按钮的Inspector窗口,添加一个点击事件:
其次是添加游戏的背景音乐(BGM)
有了前面的铺垫,我相信播放音乐也不是什么难事。只要在一个空对象上面挂上音频组件就可以了。
1.在startScene中,新建一个空对象bgmObject。
2.在该对象下创建Audio Source
,重命名为bgmSource。
3.把你的BGM文件拖到Sound
文件夹里,接着拖到bgmSource的AudioClip里。注意此时可以保持勾选Play On Awake。并且额外勾选Loop(单曲循环)。
不过问题在于,如果我想让音乐在场景切换时一直延续呢?
为了保证多个场景间的对象传递,官方提供了一个DontDestroyOnLoad()函数来保护对象不因切换场景而销毁。
为此我们需要写一个核心脚本dontDestroy
,附着在bgmObject上:
public class dontDestroy : MonoBehaviour
{
public static dontDestroy Instance;
void Start()
{
if (Instance == null)
{
DontDestroyOnLoad(gameObject);
Instance = this;
}
else if(Instance!=this)
{
Destroy(gameObject);
}
}
}
代码说明:
1.static关键字保证了Instance永远只能有一个存在,无论你有多少个dontDestry脚本。
2.那么假如出现了多个gameObject。只保留存有唯一Instance的,销毁其他的就可以了。
设置界面
一进游戏发现BGM声音好大,就做个设置音效和音乐大小的场景
这里容我偷懒转载一篇很详尽且unity版本也比较相近的他人博客吧=w=
[Unity 3D] 使用Audio Mixer分别控制主音量、背景音乐和其他音效 为此,我额外将bgmObject和sfxClick做成了预制件,所以当初点击事件那边也要相应修改一下。