【Unity/2D】Flappy Bird風ゲームを作ってみる話 #11 SEを付ける

記事をご覧いただき、誠にありがとうございます。

投稿主の無能です。

前回は、BGMが再生できるようになりました。

今回は、SEを再生してプレイヤーのジャンプ音を出したいと思います。

SEについて

それではSEについてやっていきます。

ジャンプ音のSEは前回用意したものを使います。

Roll a Ballで効果音を再生した時は、AudioSourceをアタッチしたオブジェクトが破棄されるので、PlayClipAtPointという場所を指定して音を鳴らす、という方法で実現しました。

ただ、このPlayClipAtPointでの方法だと、スペースキーでジャンプをするので、エディタの例のようにスペースキーが押された間中効果音が再生されるので、音が重なって再生されます。

今回はオブジェクトが破棄されずAudioSourceが使えるので、音が重ならないようにしていきます。

SEをインポート

ではダウンロードしてあるジャンプ音をUnityにインポートしましょう。

前回作成しておいたSEフォルダにインポートして、「SE_Jump」にリネームします。

SEフォルダにインポートして「SE_Jump」にリネーム

次はAudioSourceを準備します。

プレイヤーにAudioSourceをアタッチ

ではプレイヤーにAudioSourceをアタッチします。

アタッチしたら、音量の調節を忘れずにしましょう。
ここでは0.3にします。

そして、ジャンプしたら効果音を再生するので、Play On Awakeのチェックを外しておきます。

AudioClipもスクリプトで設定するので、Noneのままで大丈夫です。

音量を0.3、Play On Awakeのチェックを外し、AudioClipはNoneのまま

ではスクリプトを追記していきましょう。

スクリプトの追記

ではSEを再生するスクリプトの追記をしていきます。

PlayerController.cs

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

public class PlayerController : MonoBehaviour
{
    #region Var-Jump
    [Header("ジャンプ力")]
    [SerializeField] float jumpPower = 1f;
    [Header("ジャンプの効果音")]
    [SerializeField] AudioClip clip_Jump;
    #endregion

    #region Var-Internal
    Rigidbody2D playerRB;                               // プレイヤーのRigidbody2D
    public static bool isCollided = false;              // 土管との接触判定のフラグ
    AudioSource audioSource;                            // オーディオソース
    #endregion

    #region Start
    void Start()
    {
        // プレイヤーのRigidbodyを取得
        playerRB = GetComponent<Rigidbody2D>();
        // オーディオソースを取得
        audioSource = GetComponent<AudioSource>();
    }
    #endregion

    #region Update
    void Update()
    {
        // 接触フラグがtrueの場合
        if (isCollided)
        {
            // 処理を中断
            return;
        }

        // スペースキーが押された場合
        if (Input.GetKey(KeyCode.Space))
        {
            // SEを再生する
            PlaySE_Jump();
            // ジャンプする
            Jump();
        }

        // 土管との接触判定がtrueの場合
        if (isCollided)
        {
            // 処理を中断
            return;
        }
    }
    #endregion

    #region Jump
    // ジャンプする
    void Jump()
    {
        // プレイヤーに上方向のベクトルを持たせる
        playerRB.velocity = Vector2.up * jumpPower;
    }
    #endregion

    #region PlaySE_Jump
    // ジャンプのSEを再生する
    void PlaySE_Jump()
    {
        // SEを再生中の場合
        if (audioSource.isPlaying)
        {
            // 処理を中断する
            return;
        }
        // それ以外の場合
        else
        {
            // SEを一度だけ再生
            audioSource.PlayOneShot(clip_Jump);
        }
    }
    #endregion
}

では見ていきましょう。

メンバ変数

追加したメンバ変数から見ていきます。

まずジャンプのSEとなるAudioClipのclip_Jumpです。

後は内部処理用の変数で、AudioSourceのaudioSourceです。

追加したメンバ変数はこの二つになります。

Start関数

次にStart関数を見ていきます。

Start関数では、先程アタッチしたaudioSourceを取得しています。

Start関数は以上です。

Update関数

次はUpdate関数を見ていきます。

スペースキーを押すとJump関数でジャンプの処理を行うので、その前にSEを再生するPlaySE_Jump関数を追加しています。

Update関数は以上です。

PlaySE_Jump関数

次は新たに追加したPlaySE_Jump関数になります。

まず条件分岐で、アタッチしたAudioSourceが現在音を再生中の場合は、処理を中断します。

isPlayingというのはAudioSourceが持っている再生中のフラグになります。

isPlayingがtrueだと再生中、falseだと再生していない、という事になります。

これで音が重なることを防げますね。

そしてそれ以外の場合、つまりisPlayingがfalseの場合は、SEをPlayOneShotで一度だけ再生します。

PlayOneShotもAudioSourceが持っている関数になります。

音量はAudioSourceで直接変更すればいいので、今回は指定したAudioClipの引数のみとなります。

これでスクリプトの追記は以上です。

では動作確認前の準備をしていきます。

動作確認前の準備

ではUnityで動作確認前の準備をします。

プレイヤーのInspectorビューに追加された項目を設定します。

ジャンプのSEの項目ができているので、先程インポートしたSEを設定します。

追加された項目にインポートしたSEを設定

これで準備が出来ました。

動作確認

では動作確認してみましょう。

スペースキーを押してジャンプと同時にSEが鳴って、且つ音が重ならなければ大丈夫です。

音が重ならずSEが再生された

これでジャンプの効果音が実装出来ました。

上記の方法以外での実装方法

今回は割と簡単な方法でSEを音を重ねずに再生しましたが、上記の方法だと、一種類のSEだけしか音を重ならない状態で再生することしかできません。

理由は、例えばBGMを再生しているAudioSourceだと、絶えずBGMが流れているので、isPlayingがずっとtrueのままになるからです。

もし一つのAudioSourceから複数のSEを音を重ねずに鳴らしたい、という場合は、一つの例になりますが、
  • Update関数でゲーム内時間を蓄積する
  • floatで時間の閾値を設け、ゲーム内時間が閾値を超えたら再生する
  • 再生中のフラグを設け、再生中であれば処理を中断する
  • 処理が完了したら蓄積したゲーム内時間をリセット
という方法で実装できると思います。

AudioSourceを複数使う場合は、子オブジェクトにAudioSourceをアタッチし、子オブジェクトから効果音を再生するといいと思います。

もしSEが複数ある場合は、都度子オブジェクトを増やせば大丈夫です。

他にもいろいろな方法があると思うので、ご自身で考えてみてください。

まとめ

今回は
  • SEをインポートした
  • プレイヤーにAudioSourceをアタッチした
  • スクリプトでSEが再生する機能を実装した
という事をやりました。

次回は、土管を通過したらスコアを取得する仕組みを作りたいと思います。

では、また次回!

コメント