サウンド(BGM、SE)をつける

そろそろ無音なのも寂しくなってきたので、この辺で音を再生する処理を追加しましょう。

BGM・効果音素材の選定

はじめにBGMと効果音の素材を選びましょう。効果音についてはユニティちゃんのアセットの中にちょうどいいボイス素材があるので、今回はそれを利用しています。BGMはネットの音楽素材屋さんから適当に選んでインポートしてください。

サウンド管理クラスの作成

Unityで音を再生するには、まずBGMやSEを登録する必要があります。登録方法としては悪路王のときのようにAudioSourceをアタッチしていく方法でもよいのですが、この方法ではサウンドの種類が多くなると非常に面倒になってしまいます。そこでサウンド管理クラスを作り、手軽にBGMやSEを登録して再生できるようにしましょう。

新しいC#スクリプトを作り、名前を「SoundManager」に変更したらこれをGameManagerオブジェクトにアタッチしてください。そうしたら次のソースコードを記入してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoundManager : MonoBehaviour
{
	public enum SE_TYPE{ ACTION, CLEAR, GAMEOVER }

	public AudioClip[] bgm;
	public AudioClip[] actionSE;
	public AudioClip[] clearSE;
	public AudioClip[] gameOverSE;

	[SerializeField]
	[Range(0, 1)]
	float bgmVolume = 1.0f;
	[SerializeField]
	[Range(0, 1)]
	float seVolume = 1.0f;

	AudioSource bgmAudioSource;
	AudioSource seAudioSource;

	void Awake ()
	{
		bgmAudioSource = gameObject.AddComponent<AudioSource>();
		seAudioSource = gameObject.AddComponent<AudioSource>();
	}

	//BGM再生。numに0未満を指定すると停止
	public void PlayBGM(int num)
	{
		if(num >= 0)
		{
			bgmAudioSource.clip = bgm[num];
			bgmAudioSource.loop = true;
			bgmAudioSource.volume = bgmVolume;
			bgmAudioSource.Play();
		}
		else
		{
			bgmAudioSource.Stop();
		}
	}

	//SE再生
	public void PlaySE(SE_TYPE seType, int num)
	{
		switch(seType)
		{
			case SE_TYPE.ACTION:
				seAudioSource.PlayOneShot(actionSE[num], seVolume);
				break;

			case SE_TYPE.CLEAR:
				seAudioSource.PlayOneShot(clearSE[num], seVolume);
				break;

			case SE_TYPE.GAMEOVER:
				seAudioSource.PlayOneShot(gameOverSE[num], seVolume);
				break;
		}
	}

	//ランダムでSE再生
	public void RandomSE(SE_TYPE seType)
	{
		int num = 0;
		int randomRange = 0;

		switch (seType)
		{
			case SE_TYPE.ACTION:
				randomRange = actionSE.Length;
				num = Random.Range(0, randomRange);
				PlaySE(SE_TYPE.ACTION, num);
				break;

			case SE_TYPE.CLEAR:
				randomRange = clearSE.Length;
				num = Random.Range(0, randomRange);
				PlaySE(SE_TYPE.CLEAR, num);
				break;

			case SE_TYPE.GAMEOVER:
				randomRange = gameOverSE.Length;
				num = Random.Range(0, randomRange);
				PlaySE(SE_TYPE.GAMEOVER, num);
				break;
		}
	}

}

プログラムの解説

基本的な流れとしては、配列に登録したAudioClipを再生する形をとっています。

Awakeメソッド

AudioClipを再生するにはAudioSourceコンポーネントが必要なのでアタッチします。このとき、一つのAudioSourceコンポーネントにつき一つのAudioClipしか再生できないので、BGM用とSE用の2つをアタッチしておきます。なお、StartメソッドではなくAwakeなのは、Startよりも先にコンポーネントを取り付けておかないとエラーが発生する場合があるからです。

BGM再生

BGMなのでPLAY()メソッドで再生します。

SE再生

分かりやすいようにアクションごとに配列を分けておき、列挙型(enum)を使って再生する効果音を分岐させています。効果音なのでPlayOneShot()で再生します。

SEランダム再生

配列のサイズを取得し、0~配列のサイズ-1番までのSEをランダムに選んで再生します。乱数を発生させるRandom.Range(min, max)は、int型を引数に取るときはmaxを含めないので注意が必要です。

BGMやSEを登録する

プログラムができたらBGMやSEを登録していきましょう。

BGMとSEの登録

これでサウンドを鳴らすための下準備ができました。

各種スクリプトの変更

あとは必要な場所にBGMやSEを再生するための変更をくわえればOKです。

GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityStandardAssets.Characters.ThirdPerson;
using UnityStandardAssets.Cameras;

public class GameManager : MonoBehaviour
{

	[System.NonSerialized]
	public int currentStageNum = 0; //現在のステージ番号(0始まり)
	[System.NonSerialized]
	public bool countDown = false;

	[SerializeField]
	string[] stageName; //ステージ名
	[SerializeField]
	GameObject fadeCanvasPrefab;
	[SerializeField]
	GameObject gameOverCanvasPrefab;
	[SerializeField]
	float fadeWaitTime = 1.0f; //フェード時の待ち時間

	GameObject fadeCanvasClone;
	FadeCanvas fadeCanvas;
	GameObject gameOverCanvasClone;
	ThirdPersonCharacter character;
	FreeLookCam freeLookCam;
	Rigidbody playerRigidbody;
	Button[] buttons;
	SoundManager soundManager;

	//最初の処理
	void Start ()
	{
		//シーンを切り替えてもこのゲームオブジェクトを削除しないようにする
		DontDestroyOnLoad(gameObject);

		//デリゲートの登録
		SceneManager.sceneLoaded += OnSceneLoaded;

		//コンポーネントの取得
		soundManager = GetComponent<SoundManager>();
		LoadComponents();

		//BGM再生
		soundManager.PlayBGM(0);
	}

	//シーンのロード時に実行(最初は実行されない)
	void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		countDown = false;

		LoadComponents();
	}

	//コンポーネントの取得
    void LoadComponents()
    {
		//タイトル画面じゃないなら取得
		if(SceneManager.GetActiveScene().name != stageName[0])
		{
			character = GameObject.FindGameObjectWithTag("Player").GetComponent<ThirdPersonCharacter>();
			playerRigidbody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>();
			freeLookCam = GameObject.Find("FreeLookCameraRig").GetComponent<FreeLookCam>();
		}
    }

	//次のステージに進む処理
	public void NextStage()
	{
		countDown = false;

		int maxStageNum = stageName.Length - 1;

		currentStageNum += 1;

		//最後のステージの場合、タイトルに戻る
		if (currentStageNum > maxStageNum)
		{
			currentStageNum = 0;
		}

		//コルーチンを実行
		StartCoroutine(WaitForLoadScene(currentStageNum));
	}

	//任意のステージに移動する処理
	public void MoveToStage(int stageNum)
	{
		currentStageNum = stageNum;

		//コルーチンを実行
		StartCoroutine(WaitForLoadScene(stageNum));
	}

	//シーンの読み込みと待機を行うコルーチン
	IEnumerator WaitForLoadScene(int stageNum)
	{
		//タイトル画面じゃないならキャラを停止
		if (SceneManager.GetActiveScene().name != stageName[0])
		{
			character.enabled = false;
			playerRigidbody.isKinematic = true;
		}

		//フェードオブジェクトを生成
		fadeCanvasClone = Instantiate(fadeCanvasPrefab);

		//コンポーネントを取得
		fadeCanvas = fadeCanvasClone.GetComponent<FadeCanvas>();

		//フェードインさせる
		fadeCanvas.fadeIn = true;

		yield return new WaitForSeconds(fadeWaitTime);

		//シーンを非同期で読込し、読み込まれるまで待機する
		yield return SceneManager.LoadSceneAsync(stageName[stageNum]);

		//フェードアウトさせる
		fadeCanvas.fadeOut = true;
	}

	//ゲームオーバー処理
	public void GameOver()
	{
		countDown = false;

		//キャラやカメラの移動を停止させる
		character.enabled = false;
		playerRigidbody.isKinematic = true;
		freeLookCam.enabled = false;

		//ゲームオーバー画面表示
		gameOverCanvasClone = Instantiate(gameOverCanvasPrefab);

		//SE再生
		soundManager.RandomSE(SoundManager.SE_TYPE.GAMEOVER);

		//ボタンを取得
		buttons = gameOverCanvasClone.GetComponentsInChildren<Button>();

		//ボタンにイベント設定
		buttons[0].onClick.AddListener(Retry);
		buttons[1].onClick.AddListener(Return);

	}

	//リトライ
	public void Retry()
	{
		Destroy(gameOverCanvasClone);

		MoveToStage(currentStageNum);
	}

	//最初のシーンに戻る
	public void Return()
	{
		Destroy(gameOverCanvasClone);

		MoveToStage(0);
	}

	//ゲーム終了
	public void ExitGame()
	{
		Application.Quit();
	}

	//操作方法とタイトル表示の切り替え
	public void SwitchTitle(bool isTitle)
	{
		Canvas titleCanvas = GameObject.Find("Title Canvas").GetComponent<Canvas>();
		Canvas howtoCanvas = GameObject.Find("HowtoPlay Canvas").GetComponent<Canvas>();

		if (isTitle)
		{
			titleCanvas.enabled = true;
			howtoCanvas.enabled = false;
		}
		else
		{
			titleCanvas.enabled = false;
			howtoCanvas.enabled = true;
		}
	}

}

Goal.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Goal : MonoBehaviour {

	protected GameManager gameManager;
	SoundManager soundManager;

	protected void Start()
	{
		gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
		soundManager = GameObject.Find("GameManager").GetComponent<SoundManager>();
	}

	//プレイヤーが当たり判定に入った時の処理
	protected virtual void OnTriggerEnter(Collider other)
	{
		if(other.gameObject.tag == "Player")
		{
			soundManager.RandomSE(SoundManager.SE_TYPE.CLEAR);

			gameManager.NextStage();
		}
	}

}

テストプレイしてBGMやSEが再生されれば完了です!

次のページ→ゲームを完成させる

コメントを残す

メールアドレスが公開されることはありません。