FPSを作ってみよう14-銃を撃った時のエフェクトを追加する-

今回は銃を撃った時に発砲の光の表示をし発砲音を鳴らします。

また弾が当たった場所にパーティクルを表示し当たった場所がわかりやすくなるようにしていきたいと思います。

前回は

UnityのFPSゲームをJavaScriptで作ってきましたが、今回全てのスクリプトをC#に書き換えます。

でスクリプトをJavaScriptからC#への書き換えを行いました。

今後はC#スクリプトで処理を記述していきます。

スポンサーリンク

発砲の光、発砲音等を用意する

今回使用する発砲の光や発砲音、弾が当たった場所に表示するパーティクルを用意してください。

わたくしの場合はアセットストアで発砲の光のパーティクルを無料で見つけられなかったので、UnityのLightのみで光を表現するようにします。

発砲の効果音、弾が当たった場所に表示するパーティクルはとりあえずそれらしい物を用意しておけば今回の記事と同じように作成する事が出来ます。

後でちゃんとしたものを用意し取り変える事が出来ます。

WeaponStatusにエフェクト情報を保持する

銃を発砲した時のエフェクトは銃の種類によって変更する可能性があるのでWeaponStatusに情報を保持しておき、

必要になったらそこから情報を取得して利用するようにします。

現時点では効果音だけ保持しておき、他のは共通でもいいような気もしますが・・・まぁいいでしょう。

WeaponStatusスクリプトに処理を追加します。

音声やパーティクルをインスペクタで設定出来るようにし、外部スクリプトからGetterを使って取得出来るようにします。

エフェクトを設定する

WeaponStatusでエフェクト情報を保持する事が出来るようになったので、エフェクトをゲームオブジェクトに設定し、WeaponStatusのインスペクタに設定します。

まずは銃を装備しているキャラクターの階層下のEquipの辺りを開きます。

装備武器の階層

↑がEquip以下の武器の部分ですね。

効果音の設定

効果音は武器であるmakarovを選択し、インスペクタのAdd ComponentからAudio Sourceを追加します。

発砲の効果音を設定

Audio SourceのAudio Clipに銃の効果音を設定しておきます。

Play On Awakeのチェックを外しスタート時に音声が鳴らないようにしておきます。

光の設定

次に発砲時の光を設定します。

今回はパーティクルの代わりにLightを使って表現します。

武器の子要素にあるMuzzle(銃口)を選択し、インスペクタのAdd ComponentからLightを追加します。

発砲の光を表現するLight

LightのTypeはPointにし、Rangeや光の色の調整をします。

銃を撃つまでは光を表示させないのでチェックを外し無効化しておきます。

これでエフェクトの設定は終了です。

makarovを選択し、インスペクタのWeaponStatusのフィールドに今追加したAudio Source、Lightのコンポーネントを設定します。

また弾が当たった時に表示するパーティクルをshotEffectに設定してください。

これで銃を撃った時のエフェクト情報がWeaponStatusに保持されるようになりました。

銃を撃った時にエフェクトを発生させる処理をShotに追加する

WeaponStatusに銃を撃った時のエフェクト情報が保持されるようになったので、銃を撃った時にその情報を取得しエフェクトを発生させていきましょう。

銃を撃った時の処理はShotスクリプトに記述しているのでそこに処理を追加していきます。

ShotではWeaponStatusスクリプトはStartメソッドで取得しているので、その参照を使ってLightやAudioSourceのコンポーネントを操作します。

privateのShotEffectメソッドを作ります。

weaponStatusフィールドを介してGetShotSEメソッドを呼び出しAudioSourceコンポーネントを取得しそれを一旦止めた後に再生しています。

これは弾を連続で撃った時に前の再生を止めてから再生する為です。

次にGetShotLightメソッドでLightコンポーネントを取得し、一旦無効化した後に有効化します。

光はすぐに消したいのでコルーチンを使って0.2秒後に無効化し光を消しています。

コルーチンを使った処理でなくInvokeを使っても良さそうですね。

エフェクトのメソッドが出来たので後は撃った時にShotEffectメソッドを呼び出す処理を追加します。

Judgeメソッドの直後にShotEffectメソッドの呼び出しを行います。

これで銃を撃った時の効果音と光の処理が出来ました。

次に撃った弾が当たった場所にパーティクルを表示させる処理を追加していきます。

JudgeメソッドではBlockとEnemyレイヤーとの当たり判定を調べていますが、

この当たったゲームオブジェクトの情報(hits)はBlockとEnemyレイヤーに設定されたゲームオブジェクトしか入っていません。

弾が他のゲームオブジェクトに当たった時にもパーティクルを表示したいので、これとは別に当たり判定をする事にしましょう。

Physics.SphereCastを使って敵との当たり判定と同じようにします。

何らかのゲームオブジェクトに当たっていた場合はif文内が実行されるので、そこでWeaponStatusのGetShotEffectメソッドでパーティクルのゲームオブジェクトをインスタンス化しています。

パーティクルが表示されるのは弾が当たった位置で角度は親の要素(今回は親を設定しないのでワールドの角度)に設定します。

これで弾が当たった位置にパーティクルが表示されるようになります。

しかし、このパーティクルのゲームオブジェクトはインスタンス化したまま残ってしまうのでそれを消す処理が必要になってきます。

パーティクルは繰り返し実行しないように設定し、スクリプトでパーティクルの再生が終わっていたら消すようにします。

パーティクルを繰り返し再生させない

↑のようにパーティクルのLoopingのチェックを外しておけば1回再生したら止まります。

またパーティクルにDeleteParticleという名前の新しいスクリプトを作り設定します。

StartメソッドでParticleSystemの参照を取得しておきます。

Updateメソッドではパーティクルが止まっていたらDestroyでこのスクリプトが設定されているゲームオブジェクトを削除しています。

このスクリプトが設定されているのはパーティクルなのでパーティクルが削除されます。

これで全てのエフェクトの処理が追加出来ました。

銃を撃った時のエフェクトを確認する

機能が完成したので銃を撃ってエフェクトを確認してみましょう。

↑のようになりました。

光が確認しやすいようにDirectional Lightを無効にしてみましたが、画面が暗くて他が確認し辛いですね・・・(^_^;)

終わりに

エフェクトを加えるとゲームが豪華になりますね!

今回は銃を撃った時のエフェクトだけなので、その他にもゲームのBGMを追加したり歩いたり走ったりする時の効果音を加えたりするとよりゲームっぽくなってきます。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます

コメント

  1. てん より:

    こういったエフェクトを、UNETで同期させるにはどうしたらいいのでしょうか?
    プレイヤーオブジェクト以外にはCommand属性が使えないので、MuzzleのLightを同期させることができません…。

    • Rpc(リモートプロシージャコール)やCommand(コマンド)の辺りはややこしいので正確とは言えませんが、プレハブ固有のLightを他のアプリでも表示する方法を書いておきます。

      例えばプレイヤーキャラクターにLightを持たせていると仮定して話を進めます(銃を撃った時に置きかえてください)。

      プレイヤーキャラクターのLightはインスペクタでチェックを外しておき、例えば剣を振った時の振り始めでオン、振り終わりでオフにするというアニメーションイベントをアニメーションクリップに設定しておくとします。

      そうなるとアニメーションイベントの受け取りスクリプトもプレイヤーキャラクターに設定されています。

      その受け取りスクリプトをUProcessAttackとしていたらNetworkBehaviourクラスを継承して作成し、

      Lightは自身の階層から取得します。

      銃の子要素のLightの取得に関しては試行錯誤してみてください。

      アニメーションイベントが発生した時にライトのオン・オフをするので、その時にOnOffLightメソッドの引数にbool値を渡してオンかオフかを渡します。

      OnOffLightメソッドではisServerでサーバーの場合はRpcで全クライアントのRpcOnOffLightを呼び出します。

      アニメーションは同期されていて他のプレイヤーの剣を振るコマンド(マウスダウン等)に応じて自身のアプリ上の他のプレイヤーキャラクターも剣を振ります。

      他のプレイヤーキャラクターもUProcessAttackを持っているのでアニメーションイベントの受け取りをします。

      その時にサーバーとして稼働しているアプリ上でだけRpcでRpcOnOffLightを呼び出せば全クライアントでライトのオン・オフがされます。

      自身のキャラクターでない場合にUProcessAttackを無効化していると出来ないかもしれません(やってないのでわかりませんが)。

      他のやり方としては、isLocalPlayerだった時にCmdOnOffLightというCommandアトリビュートを付けたメソッドを呼び出すようにします。

      Commandアトリビュートを取り付けたメソッドはサーバーで実行されるので、その中でRpcを使ってRpcOnOffLightを呼び出すというやり方でも出来るかもしれません(こちらも作成してないのでわかりません)。

      いずれにしてもRpcを使って全クライアントでLightのオン・オフを実行しないといけないかもしれません。