i-school - 2Dタワーディフェンス 発展13
 シーン遷移の処理について、新しい実装方法を学習します。
シーン遷移の処理専用のクラスを作成し、このクラスを利用することで、シーン遷移の処理を一元化して管理するようにします。

 この機能はすべてのゲームにおいて活用可能な汎用的な機能になります。


 以下の内容で実装を進めていきます。

発展13 ーシーン遷移の実装ー
19.シーン遷移用のマネージャークラスを作成して運用する方法でシーン遷移を実装する



 新しい学習内容は、以下の通りです。

 ・enum のみのスクリプト



19.シーン遷移用のマネージャークラスを作成して運用する方法でシーン遷移を実装する

1.設計


 シーンの遷移については、スクリプト内の using 宣言に UnityEngine.SceneManagement という宣言を追加することで実装出来ます。

 例えば、複数のスクリプトに using の宣言を作成して、そこからシーンの遷移を実行してもよいですが、
こういった設計の場合、どのスクリプトからシーンの遷移を実行しているのかわかりにくく、管理もしにくい状態になります。
また、各スクリプト内にその都度 using の宣言も必要になりますので煩わしさも増えてしまいます。

 今回は今後シーンの数が増えることも想定して、シーンの遷移専用のクラスを作成して、そのクラス内ですべてのシーンの遷移の処理を管理するようにします。
このスクリプトもシングルトンデザインパターンで作成しておくことによって、すべてのスクリプトから変数の代入なく命令が出せるように出来ますので利便性が非常によくなります
また、DontDestroyOnLoad メソッドも一緒に宣言しておくことにより、シーンの遷移しても破壊されないゲームオブジェクトに出来ますので
常にゲームのシーン内に1つだけ存在し、いつでもどのスクリプトからでもシーン遷移の命令を実行することができる設計構造で実装することが出来ます。

 シーン遷移の処理は各シーンにおいて必要になる処理であるため、どのクラスからでもアクセスしやすく、いつでもシーンに存在しているクラスであることが望ましいです。
そういった観点から、今回は、シングルトンによる設計と実装を行います。


2.SceneType スクリプトを作成する


 ゲーム内に利用するシーンの名称を登録するための enum を SceneType という名前で作成し、
シーンの名称を列挙子として登録しておきます。ここには、実際に自分が作ったシーンの名前をすべて記述しておきます。
シーンが増えたら、忘れずにここに追加をします。

 なお、列挙子は一見すると文字列のように見えますが、型としては string 型ではありません
そのため、列挙子の情報を文字列として利用したい場合には、string 型へのキャスト(型変換)が必要になります

 enum のみのスクリプトは、MonoBehaviour クラスの継承がありませんので、ゲームオブジェクトに依存しません。つまり、アタッチできません。
ですが、スクリプトを作成した段階で、すべてのスクリプト内で自由に宣言して利用することができます。


SceneType.cs

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


 スクリプトを作成したらセーブします。


3.SceneStateManager スクリプトを作成する


 設計内容の復習になります。

 シーン遷移の処理には using の宣言が必要になります。
各スクリプトでバラバラにシーン遷移の処理を書くのでは、using の宣言もその都度必要なりますし、
何よりも、どのスクリプトでシーン遷移を行っているのかを把握しにくくなり、管理が煩雑になります。

 こういった処理は管理用のクラスを1つ作成し、それにすべて処理を制御させる設計を考えましょう。

 今回のケースであれば、シーン遷移についてはすべてを担当するマネージャークラスという位置づけです。

 またこういった複数のスクリプトから処理が命令される可能性のあるクラスは、
以前に学習したシングルトンデザインパターンを利用したクラスとして作成しておくとよいです。

 シーン遷移の命令を実行するにあたり、変数への代入処理が不要になりますので、
どのスクリプトからでも命令を1行記述するだけで、シーン遷移の処理を実行できる設計が実装出来ます



 シーン遷移には SceneManager.LoadScene メソッドを利用しています。
このメソッドでは引数として文字列でシーンの名前を求められますが、これは事前に string 型の変数に文字列を代入しておいたり、
enum を作成してシーンの名前を列挙子として登録しておくことによって、文字列の打ち間違えを防ぐことが出来ます。
また、enum は ToString メソッドを利用することで、列挙子を同名の文字列へとキャスト(型の変換処理)可能です。

 今回は enum で実装を行っていますので参考にしてください。enum は列挙子に登録した情報のみを対象としますので、
シーン遷移を行いたいシーンの名前のみを登録しておけば、存在しないシーンへの遷移も防ぐことができ、実行命令を記述する際にも見やすく、非常に便利です。

 つまりこれは、複数のメソッドを作成して、これは Main シーン用のメソッド、これは Battle シーン用のメソッドという風にメソッド単位で分けるのではなく
1つのメソッドを作成して、引数の値によって遷移するシーンを分岐させるという設計になっています。


SceneStateManager.cs

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


 スクリプトを作成したらセーブを行います。


4.SceneStateManager ゲームオブジェクトを作成し、SceneStateManager スクリプトをアタッチする


 SceneStateManager スクリプトをアタッチするためのゲームオブジェクトを作成します。

 ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Create Empty を選択します。
新しいゲームオブジェクトが作成されますので、名前を SceneStateManager に変更してください。

 その後、SceneStateManager スクリプトを SceneStateManager ゲームオブジェクトにドラッグアンドドロップしてアタッチしてください。


インスペクター画像



 以上でこのゲームオブジェクトの設定は完了です。


5.シーン遷移の処理を実装する


 SceneStateManager ゲームオブジェクトに SceneStateManager スクリプトをアタッチしていますので、
いずれのスクリプトからでも、GetComponent メソッドを行う必要なく、シーン遷移の処理を実装出来ます。

 実装する場合には、以下の命令文を記述します。


<Battle シーンへ遷移する場合>
 SceneStateManager.instance.PrepareteNextScene(SceneType.Battle);

 引数に設定した SceneType の列挙子のシーンへと遷移する命令になります。
ここでは、SceneType.Battle を引数にしていますので、Battle シーンへの遷移を行う命令になります。

 この引数の部分を変更することで、1つのメソッドを異なるシーンへの遷移用に使い分けることが出来ます

 すでに Battle シーンにも Debug.Log メソッドを利用して、ゲームクリアや、シーン遷移する場所を用意していますので、そちらをシーン遷移する処理へと変更して実装してみてください。


6.ゲームを実行して動作を確認する


 ステージ選択シーンからバトルシーン、そしてバトルシーンからステージ選択シーンへの遷移が行われるようになっているかを確認してください。

 SceneStateManager ゲームオブジェクトはシングルトンクラスです。そのため、複数のシーンに配置されていたとしても、必ず1つだけになるように設定されています。
デバッグのことを考えるならば、この SceneStateManager ゲームオブジェクトをプレファブにし、各シーンに配置しておくことをお勧めします。

 いずれのシーンからでもシーン遷移の処理を確認できますし、シーン遷移を行った先のシーンに SceneStateManager ゲームオブジェクトが存在していたとしても、
そちらは自動的に破壊されて常に1つだけが存在するようになるため、不具合を発生される恐れもないためです。

 なるべく効率のよいデバッグの方法を考えて実践していくといいでしょう。



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

 次は 発展14 ートランジション機能の実装− です。