Unityで銃弾を撃つスクリプトメモ②発砲音とマズルフラッシュを出す

unity 銃を撃つ マズルフラッシュ 3Dゲームの作り方
※記事内に広告が含まれています。

バーチャル3Dクリエイター神部まゆみです(*^_^*)

この記事はUnityで銃弾を撃つスクリプトについての記事です。

前回の記事はこちら。

動作確認した最新バージョンは Unity 6000.3.1 です。

●PRスペース●
■PR■

現在、約2000個の人気Unityアセットが50%オフで買える Unityニューイヤーセールをやってるみたいです。

Unityニューイヤーセール 50%オフ

Very Animation Umotion Pro なども50%オフなので、欲しいアセットはこの機会に買っておくと良いかも。

veryanimation  umotion pro   

〇まゆみマート|BOOTH

BOOTHでVRoidテクスチャやVRChat向けオブジェクトなどを販売しています。いいねしてくれると励みになります(*^-^*)

やりたいこと:銃を撃ったら発砲音とマズルフラッシュを出す

前回エイム中にボタンを押したら撃つ動作までできたので、発砲音とマズルフラッシュ(発砲光)を出すようにしたい。

アニメーションイベントの使い方を勉強したからこれで行けるかなぁ。

ChatGPTパイセンに聞いてみる

最初煙パーティクルを出そうとしましたが、マズルフラッシュのほうが手軽っぽいです。

unity 銃を撃つ 発砲音 パーティクル
神部まゆみ
神部まゆみ

UnityでTPSゲームを作っています。 銃を撃ったらアニメーションイベントで発砲音と煙のパーティクルを出すようにしたいので、スクリプトをお願いします。発砲音とパーティクルはインスペクターで指定できるようpublicになっていると嬉しいです。

ChatGPT
ChatGPT

いいですね、TPS制作!発砲の手応えって気持ちいいところなので、そこをちゃんと作ろうとしてるの分かります 👍
アニメーションイベントから呼ぶ前提で、発砲音+煙パーティクルを再生するシンプルなスクリプトを書きますね。

想定

  • 発砲アニメーションの任意のフレームで Animation Event から関数を呼ぶ
  • 効果音(AudioClip)と煙(ParticleSystem)は Inspectorで指定
  • 銃オブジェクト(またはマズル)にアタッチ

サンプルスクリプト(GunFireEffect.cs)

using UnityEngine;

public class GunFireEffect : MonoBehaviour
{
    [Header("発砲音")]
    public AudioClip gunShotSE;
    public AudioSource audioSource;

    [Header("マズル煙パーティクル")]
    public ParticleSystem muzzleSmoke;

    /// <summary>
    /// アニメーションイベントから呼ばれる関数
    /// </summary>
    public void PlayGunFireEffect()
    {
        PlaySound();
        PlayParticle();
    }

    void PlaySound()
    {
        if (audioSource != null && gunShotSE != null)
        {
            audioSource.Stop(); // 前の音を強制的に止める
            audioSource.PlayOneShot(gunShotSE);
        }
    }

    void PlayParticle()
    {
        if (muzzleSmoke != null)
        {
            muzzleSmoke.Play();
        }
    }
}

サンプルスクリプト②発砲音とマズルフラッシュ

パーティクルの代わりにライト(マズルフラッシュ)をオンオフする場合のスクリプトです。

using UnityEngine;
using System.Collections;

public class GunFireEffect : MonoBehaviour
{
    [Header("発砲音")]
    public AudioSource audioSource;
    public AudioClip gunShotSE;

    [Header("マズルフラッシュ(ライト)")]
    public Light muzzleFlashLight;
    public float flashDuration = 0.05f;

    void Awake()
    {
        // 念のため最初は消灯
        if (muzzleFlashLight != null)
        {
            muzzleFlashLight.enabled = false;
        }
    }

    /// <summary>
    /// アニメーションイベントから呼ぶ
    /// </summary>
    public void PlayGunFireEffect()
    {
        PlaySound();
        PlayMuzzleFlash();
    }

    void PlaySound()
    {
        if (audioSource != null && gunShotSE != null)
        {
            audioSource.Stop(); // 前の音を強制的に止める
            audioSource.PlayOneShot(gunShotSE);
        }
    }

    void PlayMuzzleFlash()
    {
        if (muzzleFlashLight == null)
            return;

        StopAllCoroutines();
        StartCoroutine(MuzzleFlashCoroutine());
    }

    IEnumerator MuzzleFlashCoroutine()
    {
        muzzleFlashLight.enabled = true;
        yield return new WaitForSeconds(flashDuration);
        muzzleFlashLight.enabled = false;
    }
}

Inspectorでの設定手順

  1. 銃 or マズルのGameObjectにこのスクリプトを追加
  2. AudioSource を同じオブジェクト(または子)に追加
    • Play On AwakeOFF推奨
  3. Inspectorで
    • Gun Shot SE → 発砲音のAudioClip
    • Audio Source → さっきのAudioSource
    • Muzzle Smoke → 煙のParticleSystem

アニメーションイベントの設定

  1. 発砲アニメーションを開く
  2. 音と煙を出したいフレームで Event追加
  3. 関数名に PlayGunFireEffect を指定(引数なし)

ちょいアドバイス(TPSあるある)

  • フルオート武器なら
    アニメーションじゃなく射撃処理側から呼ぶのもアリ
  • マズルフラッシュも足すなら
    Light を一瞬ON/OFFすると一気にそれっぽくなります
  • ネットワーク対応予定なら
    → この関数を RPCで呼ぶ設計にしておくと後が楽です

マズルフラッシュのほうがラクでそれっぽくできそうだからこっちにしようかな…。

煙だと撃ち終わって戦闘が終わった後に出ているイメージがある。

実際に動かしてみる

実際にやってみます。

スクリプトファイルを作ってコピペする

発砲音とマズルフラッシュのほうのスクリプトをコピペします。

発砲音素材とライトを用意する

効果音ラボさんで「拳銃を撃つ」効果音を借ります。

”銃”で検索した結果[1]|効果音ラボ

インポートしておく。

ポイントライトを銃のあたりに設置する。

これは光強めのほうがわかりやすいかな?まぁ後で調整します。

ライトはインスペクターオンのままでOK。

ライトの強さは好みで…

ちょこっと光らすだけでもいいけど、強めにするとちょっと大げさかな…?

↓はかなりライト強めにしました。

まぁ分かりやすいからアリか?(^_^;)

すぐ調整できるから後で考えるのもアリかも。

スクリプトをモデルにアタッチ、インスペクターで設定する

音を鳴らすためのオーディオソースを追加したり、ライトや発砲音のファイルを指定したりします。

アニメーションイベントを作ってスクリプトを呼ぶ

前回作ったFireアニメーションの最初のフレームにアニメーションイベントを二つ追加。

GunFireEffectスクリプトのPlaySound()とPlayMuzzleFlash()を呼ぶように設定する。

これで動いた!

これで動きました。 ※音が出ます

連射するときに音がズレる可能性があるから、銃声は短いやつを使ったほうが良いかな…。

Fire処理で呼んでしまうのもアリっぽい

ChatGPT氏に聞いたところ、こっちのほうが遅延がなくなる可能性があるっぽい?

unity 銃を撃つ 発砲音 パーティクル マズルフラッシュ アニメーションイベント

これだとAimスクリプトだけで完結しそうだな…。

アニメーションイベントを使わずAimスクリプトだけでできるやつ

こっちのほうが手軽かなぁ。処理順的には撃ったらすぐ発動するし。

Aim.csを以下のように書き換えます。

using UnityEngine;
using StarterAssets;
using System.Collections;

public class Aim : MonoBehaviour
{
    public Animator animator;

    private ThirdPersonController thirdPersonController;
    private StarterAssetsInputs starterAssetsInputs;

    [Header("発砲音")]
    public AudioSource audioSource;
    public AudioClip gunShotSE;

    [Header("マズルフラッシュ(ライト)")]
    public Light muzzleFlashLight;
    public float flashDuration = 0.05f;

    private bool isFiring;

    void Awake()
    {
        // 念のため最初は消灯
        if (muzzleFlashLight != null)
        {
            muzzleFlashLight.enabled = false;
        }
    }

    void Start()
    {
        thirdPersonController = GetComponent<ThirdPersonController>();
        starterAssetsInputs = GetComponent<StarterAssetsInputs>();
    }

    void Update()
    {
        HandleAim();
        HandleFire();
    }

    void HandleAim()
    {
        if (starterAssetsInputs.aim)
        {
            animator.SetBool("Aim", true);
            thirdPersonController.MoveSpeed = 0f;
        }
        else
        {
            animator.SetBool("Aim", false);
            thirdPersonController.MoveSpeed = 2.0f;
        }
    }

    void HandleFire()
    {
        // エイム中のみ発砲できる
        if (starterAssetsInputs.aim && starterAssetsInputs.fire)
        {
            if (!isFiring)
            {
                isFiring = true;
                animator.SetTrigger("Fire");

                // 実際の弾発射処理はここ or Animation Event
                FireBullet();
            }
        }
        else
        {
            isFiring = false;
        }
    }

    void PlaySound()
    {
        if (audioSource != null && gunShotSE != null)
        {
            audioSource.Stop(); // 前の音を強制的に止める
            audioSource.PlayOneShot(gunShotSE);
        }
    }

    void PlayMuzzleFlash()
    {
        if (muzzleFlashLight == null)
            return;

        StopAllCoroutines();
        StartCoroutine(MuzzleFlashCoroutine());
    }

    IEnumerator MuzzleFlashCoroutine()
    {
        muzzleFlashLight.enabled = true;
        yield return new WaitForSeconds(flashDuration);
        muzzleFlashLight.enabled = false;
    }

    void FireBullet()
    {
        Debug.Log("Bang!");
        // Raycast / 弾生成 / ダメージ処理など

        PlaySound();
        PlayMuzzleFlash();
    }
}

追加したGunFireEffectコンポーネントは削除、アニメーションイベントも削除して、Aimコンポーネントの設定をする。

unity 銃を撃つ マズルフラッシュ

これで動かしてみたけど…あんまり変わらないかな?(^_^;)

許容範囲ではあるけど連射するとどうしても音が止まるな…もう少し短い音を探したほうが良いかもしれない。

まぁアニメーションイベントを使わないぶん管理がラクでシンプルではあるかもしれない。

追記:音がおかしいのはアニメーションイベントを削除してないだけだった

Aim.csだけで完結するようにしたわけだけど、アニメーションイベントを削除し忘れて同じ処理が何度も行われていたっぽい(-_-;)

アニメーションイベントを削除したら連射しても音が正常になりました。

アニメーションイベント、便利だけど小さくて気づきにくいんだよなぁ…。

みなさんもご注意を。

つづく?

手軽に発砲音とマズルフラッシュが追加できて良かった。

次はやっと弾を発射したいかな(^_^;)

とりあえず弾を発射するところまでやって、その次は敵を配置して、コライダーに触れたらダメージ処理…って感じにしたいですね。

続きが書けたら追記します(*^_^*)

タイトルとURLをコピーしました