i-school - 3Dレールガンシューティング 手順5
 引き続き、プレイヤーの攻撃処理を実装します。
この手順ではエフェクトについて実装を行います。



手順5 ーエフェクト再生機能の実装ー



 ・シングルトン・デザインパターンによるクラスの運用方法



1.設計


 プレイヤー側の操作周りの実装を行います。新しく3つのクラスを作成していきます。
クラス名はこの通りである必要はありません。その場合、クラスの役割に合った名前にしてください。

 〇 PlayerController   プレイヤーの情報を管理するクラス。体力や弾数などを管理し、外部のクラスに情報提供するクラス。リロード処理、敵の攻撃の当たり判定なども管理する
             カメラのゲームオブジェクト(AR Camera、あるいは Main Camera ゲームオブジェクト)にアタッチする

<今回実装するクラス>
 ◇ EffectManager エフェクトの管理を行うクラス。Create Empty で新しいゲームオブジェクトを作成し、そこにアタッチする
             シングルトンで作成し、どのクラスからでもアクセスしやすい状態にする。エフェクトなどは個別のゲームオブジェクトに持たせないようにし、管理を簡便化できる

 ・ RayController     画面のタップ処理(マウスの左クリック)を判定し、Physics.Raycast メソッドを活用して、弾が発射できるかを管理制御するクラス
             PlayerController から弾数の情報を提供してもらい、PlayerController の弾数の値を更新したり、リロードさせる命令をだす
             カメラの子オブジェクトとして Create Empty で新しいゲームオブジェクトを作成し、そこにアタッチする


<完成時のヒエラルキー画像>


 これらがすべて完成することにより、プレイヤーの攻撃の処理が実装されます。

 イベント側(敵やアイテムなど)の実装がまだ済んでいないため、その手前までを Debug.Log メソッドを活用して実装し、
それらの実装が終了してから、再度修正を加えて完成に近づけていくようにします。


2.EffectManager クラスを作成する


 エフェクトの情報を一手に管理するためのクラスを、シングルトン・デザインパターンを利用して作成します。

 シングルトンで作成しておくことにより、どのクラスからでもアクセス(参照) しやすい状態になります。
エフェクトを個別のゲームオブジェクトに持たせないようにし、すべてこのクラスのみで管理する設計とすることで、エフェクトの登録・修正作業を簡便化できます。



 ここにゲーム内で利用するすべてのエフェクトを登録しておいて、必要なタイミングで各クラスより呼び出し命令を受けて情報を提供する設計です。
そのため、エフェクト用の変数は public 修飾子、ないしは、SerializeField 属性でインスペクターからエフェクトの登録をできるようにします。
SerializeField 属性を利用する場合には、専用のゲッターメソッドも準備するようにします。


EffectManager.cs

<= クリックすると開きます。



3.EffectManager ゲームオブジェクトを作成し、EffectManager クラスをアタッチして設定を行う


 ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Create Empty をして新しいゲームオブジェクトを作成します。
名前を EffectManager に変更し、作成した EffectManager クラスをアタッチします。

 インスペクターから GameObject 型のプレファブを登録できますので、適宜なエフェクトをアサインしてください。


<インスペクター画像>


 以上で設定は完了です。


4.<シングルトンデザインパターンによるクラスの作成>

 シングルトン とは、数多くある デザインパターン の1つです。
そのクラスのインスタンスが必ず1つであることを保証する デザインパターンのことを言います。

 EffectManager クラスでは、このシングルトンを採用しています。
つまり、ゲーム中を通じて、この EffectManager クラスが1つしか存在できないようになります。
実装例は複数ありますが、一番読みやすい方式で記述しています。



<シングルトンデザインパターンのクラスの作成方法>
    public static EffectManager instance;  // クラス名と同名の型を static で宣言する

private void Awake() {
    if (instance == null) {
        instance = this;
        DontDestroyOnLoad(gameObject);
    } else {
        Destroy(gameObject);
    }
}



ポイントは、自分自身の EffectManager 型を static 修飾子付きの instance 変数として宣言していることです。
この instance 変数が EffectManager クラス自身が代入された情報として利用することになります。

 Awake メソッドを利用して、instance 変数が null (空っぽ) である場合には、EffectManager クラス(this)を代入します。
次の DontDestroyOnLoad メソッドは Unity が用意しているメソッドで、引数に指定されたゲームオブジェクトはシーン遷移をしても破壊されてないゲームオブジェクトになります。
この DontDestroyOnLoad メソッドはシングルトンデザインパターンにする際に一緒に用いられることが多いです。

 そして instance 変数が null ではない場合、つまり、2つ目以降の複数の EffectManager クラスが存在する場合には、その EffectManager クラスのゲームオブジェクトを Destroy します。
この手順により、EffectManager クラスがアタッチされているゲームオブジェクトが常にヒエラルキー上に1つしか存在しない状態を作り出しています

 このシングルトンによってインスタンスが1つか生成されないことが保証されますので、
逆説的に考えると、この EffectManager クラスへの参照は、いずれのクラスからであっても変数を介さずに参照を行えるようになります。



 例えば、NonPlayerCharacter というクラスがあり、その NonPlayerCharacter クラスを持つゲームオブジェクトが5つあった場合、
どの」NonPlayerCharacter クラスであるかを確定できないと、対象となる NonPlayerCharacter クラスへは参照できません。
そのため、NonPlayerCharacter 型の変数を用意して、その変数へ参照したい NonPlayerCharacter クラスを代入することによって、
はじめて NonPlayerCharacter クラスの情報を扱うことができるようになります。これが情報を扱う際の基本的な処理になります。

 ですがシングルトンである EffectManager クラスの場合には、このインスタンスは常に1つしかないことが保証されていますので、
どの」という指定の部分が不要になります。よってクラスの特定ができているため、変数への代入が不要になります。
EffectManager という指定はすなわち、自動的にただ1つの EffectManager クラスの参照が行われることになるためです。

 この機能を利用して EffectManager クラスを作成しておくことで、どのクラスからでも参照しやすい設計にしておきます。



 以上でこの手順は終了です。

 => 次は 手順6 ープレイヤーの攻撃機能の実装ー です。