2016年12月23日 星期五

Day 24: 音效與背景音樂

音效及背景音樂可說是現代數位遊戲的靈魂。今天我將為遊戲加入音效與背景音樂。

在Unity為遊戲加入音樂非常簡單。只要為Game Object加入Audio Source Component,並把要播的音樂拉至Audio Clip欄,該Game Object就會發出聲音。然而,只有發出聲音的Game Object還不夠,在Scene中,還需要有一個含有Audio Listener Component的Game Object來接收聲音,音樂才會正常播放。在每個Scene中,Unity會自動為Main Camera加上Audio Listener Component,所以除非想以別的Game Object接收聲音,不然不必另做設定。

了解Unity引擎如何處理聲音後,首先來為遊戲加上最簡單的背景音樂。


到Start Scene新增一個Game Object,命名為「Background Music」,並為它加上Audio Source Component。把要播放的音樂拉到Audio Source Component的Audio Clip欄,並勾選Play On Awake(Game Object Awake時播放)和Loop(重複播放),進入Play Mode,背景音樂就會正常播放了。


遊戲場景的背景音樂作法也相同。但有兩個地方我想修改一下。第一,我希望按下暫停鈕,背景音樂也會跟著一起暫停。第二,我希望進入遊戲結束畫面時,可以降低背景音樂的音調(pitch),讓玩家有遊戲結束的感覺。

這兩點都可用Script輕鬆解決。但首先需把Background Music Game Object的Tag改成「Background Music」,這樣才能在Script中以FindGameObjectWithTag()輕鬆找到。

開一個新的C# Script,取名為「PauseBackgroundMusicOnCanvas.cs」:

public class PauseBackgroundMusicOnCanvas : MonoBehaviour 

{
    //儲存背景音樂的AudioSource Component

    private AudioSource bgMusicAudioSource;



    void OnEnable()

    {
        //在所有Game Object中找尋Background Music

        bgMusicAudioSource = GameObject.FindGameObjectWithTag ("Background Music").GetComponent< AudioSource > ();


        //暫停音樂

        bgMusicAudioSource.Pause ();

    }



    void OnDisable()

    {
        //繼續音樂

        bgMusicAudioSource.UnPause ();

    }

}

這段程式碼相當簡單。我宣告了一個AudioSource型態的變數,用以儲存背景音樂的Audio Source Component,這樣就只需呼叫一次耗費時間的GameObject.FindGameObjectWithTag()函數。

Unity的AudioSource內建Pause()UnPause()函數,所以其實根本不用多寫什麼複雜程式碼就可以讓音樂暫停了。

把這段Script加到Pause Canvas的Prefab上,之後遊戲暫停時,背景音樂也會跟著暫停了。

接著,再建立一段更簡單的Script。

public class ChangeBackgroundMusicPitchOnStart : MonoBehaviour 

{

    public float pitch; //寫改成的pitch值


    
    void Start()

    {
        //取得背景音樂

        AudioSource source = GameObject.FindGameObjectWithTag ("Background Music").GetComponent< AudioSource > ();

        source.Stop();  //暫停音樂
        source.pitch = pitch;  //改變pitch
        source.Play();  //開始音樂

    }

}

把這段Script加到Game Over Canvas的Prefab上,並設定好要改成的pitch值(大約0.5~0.7之間效果不錯,正常值為1)。進入遊戲結束畫面時,背景音樂就變得低沉且緩慢了。

搞定背景音樂後,來為遊戲加入音效吧!

音效比背景音樂還複雜一些。最直覺的做法是,把所有需要音效的Game Object都加上Audio Source Component,並勾選Play On Awake,如此該Game Object產生時就會自動發出聲音了。然而,這種做法有個致命的缺點,那就是Audio Source Component和其他Component一樣,會和擁有它們的Game Object共存亡。

舉個例子,如果把Audio Source Component加在子彈上,當主角的子彈發射時,就會發出聲音。但是,如果子彈在聲音還沒播完成就碰觸到敵子彈或敵人,音效就會隨著Game Object一起被移除,以致於播出的音效只有一半。

於是,我習慣把所有音效都包裝在一個空的Game Object Prefab內,並修改每一段要發出音效的Script,增加一行Instantiate聲音Prefab的程式碼。此外,這個擁有音效的Game Object還得加上Destroy After Seconds (Script) Component,不然時間一久,Scene上就會聚集一堆空的Game Object。

這篇文章我只示範發射子彈的音效,因為其他音效的做法一模一樣。

在Scene中新增一個Game Object,命名為「Blue Ball Audio」,並為它新增Audio Source和Destroy After Seconds (Script) Component。指定好Audio Clip、調好Volume和幾秒後要Destroy後,便可把這個Game Object拉到Project欄做成Prefab。

完成音效Prefab後,到SpawnBullet.cs增加一行變數宣告:

public GameObject shootAudio = null;


以及在GameObject bullet = (Instantiate(…) as GameObject);這行產生子彈的下方加入產生音效的程式碼:

if (shootAudio != null)

    Instantiate (shootAudio, Vector2.zero, Quaternion.identity);

因為不是每個武器射子彈都有聲音,所以我先檢查有沒有shootAudio,如果有的話(shootAudio != null),才產生音效。

回到裝備的Prefab,把剛做好的音效Prefab拉到Shoot Audio欄,射子彈的音效就完成了!


待續。

沒有留言 :

張貼留言