文章目录

  • 前言
  • 得分
  • 暂停
  • GameOver!
  • 菜单
  • 游戏音乐和音效
  • 设置界面


前言

[Unity]《太空射击》开发日记Ep.2(初级篇) 麻雀虽小五脏俱全,一个再简陋的游戏也不能少了界面设计。也就是得分,菜单,设置等等,这些功能让游戏成为了一个可控的完整系统。

得分

游戏里要显示一个坚持的时间作为得分,类似Score:xx.xx

Unity中使用一个叫Canvas的对象来管理所有的UI,也就是界面对象。Canvas渲染后会覆盖到游戏画面上,但不会干预游戏的进行,就像加了层滤膜一样。

Canvas会在我们创建UI控件时自动出现,于是我们先创建一个txtScore。

在Hierarchy窗口中,右键UI>Text,重命名为txtScore。

然后要分两大块处理:

第一块,UI在场景中的位置。双击txtScore之后就会定位到它的位置,你会发现除了X,Y的箭头外,还有一个四叶草一样的东西,这是锚点,是定位相对位置所用的。比如我放置的分数在左上角,我会把锚点也拖到左上角去。

unity 点击播放音效_sed


第二块,UI的属性设置。你会发现我已经改好了文本内容和颜色,其实想想也知道是在Inspector窗口改的,具体点的话,我更改了Text和Color两个属性。

现在直接运行,就能看到新添加的文本框了。

unity 点击播放音效_sed_02


如何让分数随着时间递增呢

因为分数只与时间有关,所以分数变化还是很简单的。关键在于如何去修改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属性哦。

最后的效果非常理想:

unity 点击播放音效_unity 点击播放音效_03

暂停

接下来要做一个暂停功能,按下’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出来:

unity 点击播放音效_unity 点击播放音效_04


注意我额外设置了文字水平垂直居中,锚点也是默认中心位置。

接下来我的设想是,开始时该文本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的事件列表:

unity 点击播放音效_Time_05


这个已经充分说明了按钮的点击事件是通过加载一个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

unity 点击播放音效_sed_06


“退出游戏“按钮也同理。

到此,一个拥有基本功能的菜单就完成了。

游戏音乐和音效

终于可以开始添加游戏声音了,从按钮的点击音效(SFX)开始吧

音效添加因为是一个比较常用的功能,因此Unity有现成的方法。

1.在需要添加音频的按钮上右键Audio>Audio Source,重命名为sfxClick。

2.项目文件里新建Sound文件夹,把你的音效文件sfx.mp3拖进去。

3.把sfx.mp3拖到Audio Source下的AudioClip里 ,并且把Play On Awake的√去除。

4.回到按钮的Inspector窗口,添加一个点击事件:

unity 点击播放音效_UI_07


其次是添加游戏的背景音乐(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做成了预制件,所以当初点击事件那边也要相应修改一下。