読者です 読者をやめる 読者になる 読者になる

Unity5(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity7】BGMと効果音を付ける【2Dローグライク13】

Unity 2D ローグライク チュートリアル

いつもひよこのたまごをご利用下さいましてありがとうございます!
おかげ様でチュートリアル数も10ゲーム目となりました!
チュートリアル一覧は
こちら からどうぞ!


スポンサーリンク

Unity5.0.0f4 Personal(2015年6月)

f:id:hiyotama:20150519220636p:plain

前回の続きです〜

今回は、ゲームにBGMと効果音をつけていきます〜


UnityのAudio機能について以前エッセンスを書きましたので、予めご参照下さると進めやすいと思います〜

hiyotama.hatenablog.com

【目標】ゲームにBGMと効果音を付ける!



2D Roguelike 13 of 14 : Audio - YouTube



①SoundManagerオブジェクトの作成
まずは音を管理する、SoundManagerオブジェクトを作成します〜HierarchyからCreateEmptyを選択し、
名前をSoundManagerに変更します〜


f:id:hiyotama:20150603113259p:plain
SoundManagerオブジェクト作成


続いてSoundManagerオブジェクトにAudioSourceをふたつ付けます〜SoundManagerのInspectorビューにあるAddComponentより、Audio>AudioSourceと進んで取り付けて下さい〜


f:id:hiyotama:20150603113502p:plain
AudioSourceをふたつ取り付ける


②SoundManagerスクリプトを作成する
それではSoundManagerオブジェクトに取り付けるSoundManagerスクリプトを作成していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;

public class SoundManager : MonoBehaviour {
	
	public AudioSource efxSource; //効果音用AudioSource
	public AudioSource musicSource; //BGM用AudioSource
	public static SoundManager instance = null;
	//音の高さにバリエーションを付ける用の変数
	public float lowPitchRange = .95f;
	public float highPitchRange = 1.05f;
	
	//シングルトンの処理
	void Awake ()
	{
		if (instance == null)
			instance = this;
		else if (instance != this)
			Destroy (gameObject);
		
		DontDestroyOnLoad (gameObject);
	}
	
	//BGMの再生
	public void PlaySingle (AudioClip clip)
	{
		efxSource.clip = clip;
		efxSource.Play();
	}
	
	//数種類の効果音を受け取り、ランダムで再生
	public void RandomizeSfx (params AudioClip[] clips)
	{
		//受け取った効果音番号をランダムで指定
		int randomIndex = Random.Range(0, clips.Length);
		//音の高さをランダムで指定
		float randomPitch = Random.Range(lowPitchRange, highPitchRange);
		efxSource.pitch = randomPitch;
		//受け取った効果音を選択
		efxSource.clip = clips[randomIndex];
		//効果音を再生
		efxSource.Play();
	}
}

SoundManage.cs


Awakeメソッドでは、シングルトンの機能をのせています〜シングルトンについてはGameManager作成時に紹介していますので、ご参照下さい〜

hiyotama.hatenablog.com


続いてPlaySingleメソッドです〜ここではAudioClipを受け取り、BGMを再生しています〜


最後にRandomizeSfxメソッドです〜ここでは引数として複数の効果音(このゲームでは2種類の効果音)を受け取り、それらをランダムで選択し再生しています〜


まずは受け取った効果音数からランダムで1つ決定します〜


次に音の高さをランダムで指定します〜pitch(音の高さ)は、基本の高さが1で、今回0.95〜1.05の範囲からランダムで指定する形となっています〜


次にAudioSourceのclipを設定していきます〜
引数として受け取ったclips配列の中からrandomIndex番目の効果音を選択し、clipに指定します〜


最後にPlayメソッドで効果音を再生します〜


スクリプトができましたらSoundManagerオブジェクトに取り付け、BGMの設定をしていきます〜


SoundManagerオブジェクトについているAudioSourceのうち、2番目のAudioSourceのAudioClipに「scavengers_music」を指定します〜また、BGMなのでLoopをtrueにして下さい〜

1番目のAudioSourceについてはPlay On aAwakeをfalseにだけしておいて下さい〜


f:id:hiyotama:20150603120441p:plain
こんな感じ


最後にSoundManagerスクリプトのpublic変数efxSourceに1番目のAudioSourceを、musicSourceに2番目のAudioSourceを指定して下さい〜


f:id:hiyotama:20150603120820p:plain
ドラッグ&ドロップ!


③Playerスクリプトに効果音の処理を追加する
Playerスクリプトに効果音を鳴らす処理を追加していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Player : MovingObject {
	
	public int wallDamage = 1;
	public int pointsPerFood = 10;
	public int pointsPerSoda = 20;
	public float restartlevelDelay = 1f;
	public Text foodText;
//********** 開始 **********//
	//各効果音を指定
	public AudioClip moveSound1;
	public AudioClip moveSound2;
	public AudioClip eatSound1;
	public AudioClip eatSound2;
	public AudioClip drinkSound1;
	public AudioClip drinkSound2;
	public AudioClip gameOverSound;
//********** 終了 **********//
	
	private Animator animator;
	private int food;

	protected override void Start () {
		animator = GetComponent<Animator>();
		food = GameManager.instance.playerFoodPoints;
		foodText.text = "Food: " + food;
		base.Start();
	}

	private void OnDisable ()
	{
		GameManager.instance.playerFoodPoints = food;
	}

	void Update ()
	{
		if (!GameManager.instance.playersTurn)
			return;
		
		int horizontal = 0;
		int vertical = 0;
		
		horizontal = (int)Input.GetAxisRaw ("Horizontal");
		vertical = (int)Input.GetAxisRaw ("Vertical");

		if (horizontal != 0) {
			vertical = 0;
		}
		if (horizontal != 0 || vertical != 0) {
			AttemptMove<Wall>(horizontal, vertical);
		}
	}
	
	protected override void AttemptMove <T> (int xDir, int yDir)
	{
		food--;
		foodText.text = "Food: " + food;
		base.AttemptMove <T> (xDir, yDir);
		
		RaycastHit2D hit;
//********** 開始 **********//
		//移動可能である時、moveSound1かmoveSound2どちらかを鳴らす
		if (Move (xDir, yDir, out hit)) {
			SoundManager.instance.RandomizeSfx(moveSound1, moveSound2);
		}
//********** 終了 **********//
		CheckIfGameOver();
		GameManager.instance.playersTurn = false;
	}
	
	protected override void OnCantMove <T> (T component)
	{
		Wall hitWall = component as Wall;
		hitWall.DamageWall(wallDamage);
		animator.SetTrigger("PlayerChop");
	}
	
	private void OnTriggerEnter2D (Collider2D other)
	{
		if (other.tag == "Exit") {
			Invoke ("Restart", restartlevelDelay);
			enabled = false;
		} else if (other.tag == "Food") {
			food += pointsPerFood;
			foodText.text = "+" + pointsPerFood + " Food: " + food;
//********** 開始 **********//
			//Foodを取った時、eatSound1かeatSound2を鳴らす
			SoundManager.instance.RandomizeSfx(eatSound1, eatSound2);
//********** 終了 **********//
			other.gameObject.SetActive(false);
		} else if (other.tag == "Soda") {
			food += pointsPerSoda;
			foodText.text = "+" + pointsPerSoda + " Food: " + food;
//********** 開始 **********//
			//Sodaを取った時、drinkSound1かdrinkSound2を鳴らす
			SoundManager.instance.RandomizeSfx(drinkSound1, drinkSound2);
//********** 終了 **********//
			other.gameObject.SetActive(false);
		}
	}
	
	private void Restart ()
	{
		Application.LoadLevel(Application.loadedLevel);
	}
	public void LoseFood (int loss)
	{
		animator.SetTrigger("PlayerHit");
		food -= loss;
		foodText.text = "-" + loss + " Food: " + food;
		CheckIfGameOver();
	}
	
	private void CheckIfGameOver ()
	{
		if (food <= 0) {
//********** 開始 **********//
			//gameOverSoundを鳴らす
			SoundManager.instance.PlaySingle(gameOverSound);
			//BGMは停止する
			SoundManager.instance.musicSource.Stop();
//********** 終了 **********//
			GameManager.instance.GameOver();
		}
	}
}


メンバ変数として、たくさんのAudioClipを指定しています〜これらはpublic変数なので、Inspectorより設定していきます〜

まずはmoveSound1にはscavengers_footstep1を指定して下さい〜


f:id:hiyotama:20150603121753p:plain
ドラッグ&ドロップ!


同じ要領で、
moveSound2 = scavengers_footstep2
eatSound1=scavengers_fruit1
eatSound2=scavengers_eatSound2
drinkSound1=scavengers_soda1
drinkSound2=scavengers_soda2
gameOverSound=scavengers_dir
を指定して下さい〜

それではスクリプトの解説に入っていきます〜
まずはAttemptMoveメソッドにて、Moveメソッドを実行し、trueが帰ってきたら移動可能ということなので、歩く音を鳴らしていきます〜

シングルトンであるSoundManagerクラスにアクセスし、RandomizeSfxメソッドを呼び出しています〜引数にはmoveSound1とmoveSound2と2つの効果音を指定し、どちらか一方をランダムで鳴らしています〜


OnTriggerEnter2Dメソッドでも、同じような処理を行っています〜アイテムを取ったタイミングでSoundManagerクラスのRandomizeSfxメソッドを実行しています〜


最後のCheckIfGameOverメソッドでは単一の効果音を渡すので、SoundManagerクラスのPlaySingleメソッドを実行しています〜引数にはgameOverSoundのみを指定しています〜また、BGMをこのタイミングでStopしています〜


④Enemyスクリプトに効果音処理を追加する
続いてEnemyが攻撃した時に効果音を発生させるため、Enemyスクリプトに加筆していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;
public class Enemy : MovingObject {
	
	public int playerDamage;
	
	private Animator animator;
	private Transform target;
	private bool skipMove; 
//********** 開始 **********//
	//攻撃用の効果音を指定
	public AudioClip enemyAttack1;
	public AudioClip enemyAttack2;
//********** 終了 **********//
	
	protected override void Start () {
		GameManager.instance.AddEnemyToList(this);
		animator = GetComponent<Animator>();
		target = GameObject.FindGameObjectWithTag("Player").transform;
		base.Start();
	}

	protected override void AttemptMove <T> (int xDir, int yDir)
	{
		if (skipMove) {
			skipMove = false;
			return;
		}
		
		base.AttemptMove <T> (xDir, yDir);
		skipMove = true;
	}

	public void MoveEnemy ()
	{
		int xDir = 0;
		int yDir = 0;

		if (Mathf.Abs (target.position.x - transform.position.x) < float.Epsilon) {
			yDir = target.position.y > transform.position.y ? 1 : -1;
		} else {
			xDir = target.position.x > transform.position.x ? 1 : -1;
		}
		AttemptMove <Player> (xDir, yDir);
	}
	
	protected override void OnCantMove <T> (T component)
	{
		Player hitPlayer = component as Player;
		animator.SetTrigger("enemyAttack");
		hitPlayer.LoseFood(playerDamage);
//********** 開始 **********//
		//攻撃用効果音をSoundManagerに渡し、ランダムで再生
		SoundManager.instance.RandomizeSfx(enemyAttack1, enemyAttack2);
//********** 終了 **********//
	}
}

Enemy.cs


メンバー変数にpublicでAudioClipを2つ作成しましたので、Inspectorビューから指定していきます〜


PrefabフォルダからEnemy1とEnemy2を選択し、InspectorビューのenemyAttack1にscavengers_enemy1を、enemyAttack2にscavengers_enemy2を指定します〜


f:id:hiyotama:20150603123359p:plain
AudioClipを指定


OnCantMoveメソッドにて先ほどと同様、効果音2つを引数にSoundManagerクラスのRandomizeSfxメソッドを呼び出しています〜


⑤Wallスクリプトに効果音処理を追加する
最後にプレイヤーがWallを攻撃した時に音を出すため、Wallスクリプトに加筆していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;

public class Wall : MonoBehaviour {
//********** 開始 **********//
	public AudioClip chopSound1;
	public AudioClip chopSound2;
//********** 終了 **********//
	public Sprite dmgSprite;
	public int hp = 3;

	private SpriteRenderer spriteRenderer;

	void Awake ()
	{
		spriteRenderer = GetComponent<SpriteRenderer> ();
	}

	public void DamageWall (int loss)
	{
//********** 開始 **********//
		SoundManager.instance.RandomizeSfx (chopSound1, chopSound2);
//********** 終了 **********//
		spriteRenderer.sprite = dmgSprite;
		hp -= loss;
		if(hp <= 0)
			gameObject.SetActive (false);
	}
}

Wall.cs


これまでと全く同じ要領で効果音を出すことができます〜
まずは、PrefabフォルダにあるWall1〜Wall8を選択した状態で、public変数chopSound1にscavengers_chop1を、chopSound2にscavengers_chop2を指定します〜


f:id:hiyotama:20150603123815p:plain
Wall1〜Wall8を選択した状態でAudioSourceを指定


DamageWallメソッドの先頭でSoundManagerクラスのRandomizeSfxメソッドを実行しています〜引数には効果音2つを指定しています〜


今回は音の実装のためテスト結果の表示はブログでは難しいので、ここまでとします〜
ありがとうございました〜


【Unity開発7】Unity公式チュートリアル2Dローグライクの導入【2Dローグライク1】

【Unity開発7】アニメーションを作りたい!【2Dローグライク2】

【Unity開発7】Floorやアイテムを作成したい!【2Dローグライク3】

【Unity開発7】床や敵キャラ、アイテム等を自動生成させたい!【2Dローグライク4】

【Unity開発7】BoardManagerを呼び出すGameManagerを作成する【2Dローグライク5】

【Unity開発7】キャラクターを動かすための抽象クラス作成【2Dローグライク6】

【Unity開発7】破壊可能な壁(Wall)を作成したい!【ローグライク7】

【Unity開発7】プレイヤーのアニメーターを設定したい!【ローグライク8】

【Unity開発7】プレイヤー用のスクリプトを設定したい!【ローグライク9】

【Unity開発7】敵キャラクターのスクリプトを作成したい!【2Dローグライク10】

【Unity開発7】敵キャラクターのアニメーターを設定したい!【2Dローグライク11】

【Unity開発7】uGUIでUIの表示とレベル機能を実装したい!【2Dローグライク12】

【Unity開発7】BGMと効果音を付ける【2Dローグライク13】

【Unity開発7】タッチパネルに対応させたい!【2Dローグライク14(Fin)】