今回は銃を撃った時に発砲の光の表示をし発砲音を鳴らします。
また弾が当たった場所にパーティクルを表示し当たった場所がわかりやすくなるようにしていきたいと思います。
前回は
でスクリプトをJavaScriptからC#への書き換えを行いました。
今後はC#スクリプトで処理を記述していきます。
発砲の光、発砲音等を用意する
今回使用する発砲の光や発砲音、弾が当たった場所に表示するパーティクルを用意してください。
わたくしの場合はアセットストアで発砲の光のパーティクルを無料で見つけられなかったので、UnityのLightのみで光を表現するようにします。
発砲の効果音、弾が当たった場所に表示するパーティクルはとりあえずそれらしい物を用意しておけば今回の記事と同じように作成する事が出来ます。
後でちゃんとしたものを用意し取り変える事が出来ます。
WeaponStatusにエフェクト情報を保持する
銃を発砲した時のエフェクトは銃の種類によって変更する可能性があるのでWeaponStatusに情報を保持しておき、
必要になったらそこから情報を取得して利用するようにします。
現時点では効果音だけ保持しておき、他のは共通でもいいような気もしますが・・・まぁいいでしょう。
WeaponStatusスクリプトに処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [SerializeField] private AudioSource shotSE; // 銃の発砲音 [SerializeField] private Light shotLight; // 銃の光 [SerializeField] private GameObject shotEffect; // 弾が当たった時のパーティクル public AudioSource GetShotSE() { return shotSE; } public Light GetShotLight() { return shotLight; } public GameObject GetShotEffect() { return shotEffect; } |
音声やパーティクルをインスペクタで設定出来るようにし、外部スクリプトからGetterを使って取得出来るようにします。
エフェクトを設定する
WeaponStatusでエフェクト情報を保持する事が出来るようになったので、エフェクトをゲームオブジェクトに設定し、WeaponStatusのインスペクタに設定します。
まずは銃を装備しているキャラクターの階層下のEquipの辺りを開きます。
↑がEquip以下の武器の部分ですね。
効果音の設定
効果音は武器であるmakarovを選択し、インスペクタのAdd ComponentからAudio Sourceを追加します。
Audio SourceのAudio Clipに銃の効果音を設定しておきます。
Play On Awakeのチェックを外しスタート時に音声が鳴らないようにしておきます。
光の設定
次に発砲時の光を設定します。
今回はパーティクルの代わりにLightを使って表現します。
武器の子要素にあるMuzzle(銃口)を選択し、インスペクタのAdd ComponentからLightを追加します。
LightのTypeはPointにし、Rangeや光の色の調整をします。
銃を撃つまでは光を表示させないのでチェックを外し無効化しておきます。
これでエフェクトの設定は終了です。
makarovを選択し、インスペクタのWeaponStatusのフィールドに今追加したAudio Source、Lightのコンポーネントを設定します。
また弾が当たった時に表示するパーティクルをshotEffectに設定してください。
これで銃を撃った時のエフェクト情報がWeaponStatusに保持されるようになりました。
銃を撃った時にエフェクトを発生させる処理をShotに追加する
WeaponStatusに銃を撃った時のエフェクト情報が保持されるようになったので、銃を撃った時にその情報を取得しエフェクトを発生させていきましょう。
銃を撃った時の処理はShotスクリプトに記述しているのでそこに処理を追加していきます。
ShotではWeaponStatusスクリプトはStartメソッドで取得しているので、その参照を使ってLightやAudioSourceのコンポーネントを操作します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 発砲時のエフェクト処理 private void ShotEffect() { // 効果音の再生 weaponStatus.GetShotSE ().Stop (); weaponStatus.GetShotSE ().Play (); // 光を表示 weaponStatus.GetShotLight ().enabled = false; weaponStatus.GetShotLight ().enabled = true; // コルーチンでライトを消す処理を実行 StartCoroutine (DisableLight()); // ライトを消す処理 IEnumerator DisableLight() { yield return new WaitForSeconds (0.2f); weaponStatus.GetShotLight ().enabled = false; } } |
privateのShotEffectメソッドを作ります。
weaponStatusフィールドを介してGetShotSEメソッドを呼び出しAudioSourceコンポーネントを取得しそれを一旦止めた後に再生しています。
これは弾を連続で撃った時に前の再生を止めてから再生する為です。
次にGetShotLightメソッドでLightコンポーネントを取得し、一旦無効化した後に有効化します。
光はすぐに消したいのでコルーチンを使って0.2秒後に無効化し光を消しています。
コルーチンを使った処理でなくInvokeを使っても良さそうですね。
エフェクトのメソッドが出来たので後は撃った時にShotEffectメソッドを呼び出す処理を追加します。
1 2 3 4 5 6 7 | public void Judge() { // 銃を打った時のエフェクトを実行 ShotEffect (); |
Judgeメソッドの直後にShotEffectメソッドの呼び出しを行います。
これで銃を撃った時の効果音と光の処理が出来ました。
次に撃った弾が当たった場所にパーティクルを表示させる処理を追加していきます。
JudgeメソッドではBlockとEnemyレイヤーとの当たり判定を調べていますが、
1 2 3 | hits = Physics.SphereCastAll(ray, muzzleRadius, shotRange, LayerMask.GetMask("Block", "Enemy")); |
この当たったゲームオブジェクトの情報(hits)はBlockとEnemyレイヤーに設定されたゲームオブジェクトしか入っていません。
弾が他のゲームオブジェクトに当たった時にもパーティクルを表示したいので、これとは別に当たり判定をする事にしましょう。
1 2 3 4 5 6 7 8 9 | // エフェクト用RaycastHit RaycastHit effectHit; if (Physics.SphereCast (ray, muzzleRadius, out effectHit, shotRange)) { GameObject.Instantiate (weaponStatus.GetShotEffect (), effectHit.point, Quaternion.identity); } |
Physics.SphereCastを使って敵との当たり判定と同じようにします。
何らかのゲームオブジェクトに当たっていた場合はif文内が実行されるので、そこでWeaponStatusのGetShotEffectメソッドでパーティクルのゲームオブジェクトをインスタンス化しています。
パーティクルが表示されるのは弾が当たった位置で角度は親の要素(今回は親を設定しないのでワールドの角度)に設定します。
これで弾が当たった位置にパーティクルが表示されるようになります。
しかし、このパーティクルのゲームオブジェクトはインスタンス化したまま残ってしまうのでそれを消す処理が必要になってきます。
パーティクルは繰り返し実行しないように設定し、スクリプトでパーティクルの再生が終わっていたら消すようにします。
↑のようにパーティクルのLoopingのチェックを外しておけば1回再生したら止まります。
またパーティクルにDeleteParticleという名前の新しいスクリプトを作り設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using UnityEngine; using System.Collections; public class DeleteParticle : MonoBehaviour { private ParticleSystem particle; // Use this for initialization void Start () { particle = GetComponent <ParticleSystem> (); } // Update is called once per frame void Update () { if (particle.isStopped) { Destroy (this.gameObject); } } } |
StartメソッドでParticleSystemの参照を取得しておきます。
Updateメソッドではパーティクルが止まっていたらDestroyでこのスクリプトが設定されているゲームオブジェクトを削除しています。
このスクリプトが設定されているのはパーティクルなのでパーティクルが削除されます。
これで全てのエフェクトの処理が追加出来ました。
銃を撃った時のエフェクトを確認する
機能が完成したので銃を撃ってエフェクトを確認してみましょう。
↑のようになりました。
光が確認しやすいようにDirectional Lightを無効にしてみましたが、画面が暗くて他が確認し辛いですね・・・(^_^;)
終わりに
エフェクトを加えるとゲームが豪華になりますね!
今回は銃を撃った時のエフェクトだけなので、その他にもゲームのBGMを追加したり歩いたり走ったりする時の効果音を加えたりするとよりゲームっぽくなってきます。