君がゲームを作る!Unityゲーム開発入門
第50回 効果音を鳴らしてみよう

歩きスマホって、たまにガチで電柱にぶつかるよね

みなさん、こんにちは!

お風呂場のタイル目地の掃除は、入浴しながらやれば蒸気の力でみるみるカビが落ちることを知っているあらたまです。

さて今日は「君がゲームを作る!Unityゲーム開発入門」の第50回目です。

おさらい

前回 はゲームのBGMを鳴らすように設定しましたね。

今日は、効果音を鳴らすようにしたいと思います!

音楽素材を用意する

今回は、キャラクターが山にぶつかったときに効果音を鳴らしたいと思います。

まずはBGM用の音楽素材を用意しましょう。

今回は8bitサウンド工房さんから素材をお借りしたいと思います。

「効果音」をクリックします。

「壁にぶつかる_1」を右クリックからダウンロードします。

音楽ファイルを取り込む

続いて、ダウンロードしたファイルをプロジェクトに取り込みましょう。

プロジェクトウィンドウの「Sounds」フォルダを選択し、 「Assets」メニューの「Create」から「Folder」をクリックします。

作成されたフォルダの名前を「SE」(サウンドエフェクト・効果音)に変更しておきます。

プロジェクトウィンドウで「SE」フォルダーを選択し、さきほどダウンロードした音楽ファイルを ドラッグ&ドロップして取り込みます。

キャラクターにコンポーネントを追加する

続いて、キャラクターに「効果音を鳴らす」ためのコンポーネントを追加、設定します。

コンポーネントの追加

ヒエラルキーウィンドウで「yusya」を選択し、インスペクターウィンドウで「Add Component」をクリックします。

「Audio」をクリックします。

「Audio Source」をクリックします。

「Audio Source」コンポーネントが追加されました!

コンポーネントへ音楽ファイルを設定

プロジェクトウィンドウでの音楽ファイルを、インスペクターウィンドウの「Audio Clip」欄に ドラッグ&ドロップします。

自動再生をOFFにする

今回はキャラクターが山にぶつかったときに音を鳴らしますので、 再生の自動開始はオフにしておきましょう。

インスペクターウィンドウの「Play on Awake」欄のチェックを外します。

山にぶつかったタイミングで音を鳴らす

続いて、山にぶつかったタイミングで音を鳴らすプログラミングをしましょう。

プロジェクトウィンドウの「YusyaControl」を選択し、インスペクターウィンドウで「Open」をクリックします。

下記のように太字の部分を追加してください。

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

public class YusyaControl : MonoBehaviour
{
    // ... 省略 ...

    void OnCollisionStay2D(Collision2D col)
    {
        // 衝突したレイヤーの名前を取得
        string layerName = LayerMask.LayerToName(col.gameObject.layer);

        //// レイヤー名がWallの時は音を再生
        if (layerName == "Wall")
        {
            GetComponent<AudioSource>().Play();
        }
    }
}

OnCollisionStay2Dメソッド

コライダーとコライダーが衝突している間、呼び出されます。
今回の場合、キャラクターと山が衝突している間、呼び出されるわけですね。

引数の「Collision2D col」には衝突した相手のコライダーコンポーネントが渡されます。

LayerMask.LayerToName(col.gameObject.layer);

衝突した相手のレイヤー名を取得しています。

GetComponent<AudioSource>().Play();

「AudioSource」コンポーネントの再生処理を呼び出しています。

タイルマップのレイヤーを「Wall」に変更する

プログラムを見てみると、キャラクターが衝突した相手のレイヤー名が「Wall」 であった場合に、音声を鳴らしていることがわかりますね。

では、山のタイルマップのレイヤーを「Wall」に設定しましょう。

ヒエラルキーウィンドウで「MountainTileMap」を選択し、 インスペクターウィンドウでレイヤーの欄をクリックします。

「Add Layer」をクリックします。

「User Layer 8」に「Wall」と入力します。

もう一度ヒエラルキーウィンドウで「MountainTileMap」を選択し、 インスペクターウィンドウでレイヤーの欄をクリック、「Wall」を選択します。

タイルマップのレイヤーが「Wall」に変わりました!

テストプレイで動作確認をする

では、テストプレイして動作を確認してみましょう!
上部中央の▶ボタンを押して、プレイモードに入ります。

山に衝突すると「ドゥン」と効果音が鳴りました。

しかし横に移動すると、、新しい山とすれ違うたびに 音が鳴ってしまいます。。

すれ違いに「それぞれの山と衝突している」とみなされてしまっているためです。 これを直していきましょう!

音を鳴らす条件を変更する

プロジェクトウィンドウの「YusyaControl」を選択し、インスペクターウィンドウで「Open」をクリックします。

下記のように太字の部分を追加してください。

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

public class YusyaControl : MonoBehaviour
{
    // ... 省略 ...

    void OnCollisionStay2D(Collision2D col)
    {
        // 衝突したレイヤーの名前を取得
        string layerName = LayerMask.LayerToName(col.gameObject.layer);

        //// レイヤー名がWallの時は音を再生
        if (layerName == "Wall")
        {
            // キャラクターの中心位置
            Vector3 yusyaPosition = transform.position;
            // キャラクターと山が衝突した位置
            Vector2 hitPosition = col.GetContact(0).point;

            // 押されている矢印キーの方向と、
            // 衝突した方向が一致しているときのみ 音を鳴らす
            if ((Input.GetKey("down") && hitPosition.y < yusyaPosition.y)
                || (Input.GetKey("right") && hitPosition.x > yusyaPosition.x)
                || (Input.GetKey("up") && hitPosition.y > yusyaPosition.y)
                || (Input.GetKey("left") && hitPosition.x < yusyaPosition.x))
            {
                GetComponent<AudioSource>().Play();
            }
        }
    }
}

transform.position

キャラクターがいる位置を取得しています。

col.GetContact(0).point

キャラクターと山が衝突した接点の位置を取得しています。

ifの分岐

キャラクターの位置と衝突点の位置を比較することで、キャラクターの上下左右どこで衝突が発生したかを判定しています。

そしてその衝突した上下左右の方向と、押されている矢印キーの上下左右が一致しているときのみ (=キャラクターが向いている方向に山があるときのみ)音を鳴らすようにしています。

テストプレイで動作確認をする

それでは、テストプレイして動作を確認してみましょう!
上部中央の▶ボタンを押して、プレイモードに入ります。

山にぶつかると「ドゥン」と音がなりました。

横に向かって移動しているときには音は鳴らずに…

山に行き当たるとまた音が鳴りましたね!

今回はここまでです!

次回は町への入りかたをやってみたいと思います。

次回へ続く。

>> 続きの記事
【君がゲームを作る!Unityゲーム開発入門】第51回 町の中に入ってみよう