i-school - 3Dレールガンシューティング 手順17
 ゲームの進行状況を管理するための機能を実装します。



手順17 ーゲームの進行状況管理機能ー

<学習内容>
 ・WaitUntil クラス



設計


 ゲーム内の処理において、現在のゲームの進行状態がどのような場面であるかを判定する必要があるケースがあります。
ですが、Unity 自体にはそのような機能はないため、自作して、ゲームの進行状態を管理しておく必要があります。

 管理の方法には、enum を利用します。これは、列挙子としてゲームの進行状態の候補を事前に登録しておくことが出来、
かつ、変数に代入して管理を行う際には、列挙子のいずれか1つしか代入できないため、排他的な処理を作ることに適しているためです。

 ゲームの進行状態とは、単一の状態で表現することが重要になります。
ゲームプレイ中という状態とゲーム待機中という状態が、同じにあってはなりません。
よって、ある1つの状態になっている際には、他の状態にはならない(一緒に競合した状態を作らない)ことが大切です。

 enum による管理は、この部分を表現可能です。
つまり、enum の列挙子が A という状態であるならば、他の列挙子である B や C という状態にはならない、ということが保証されるため、
ゲームの進行状態を表現する際にとても運用しやすいと言えます。

 最初に GameState の enum を作成し、それを活用したゲームの進行状態を管理する機能を実装します。

 GameState 変数の管理は、GameManager クラスにおいて行い、他のクラスは、この GameManager クラスにて管理されている
GameState 変数の情報を「現在のゲームの進行状態」として参照する設計にしています。


GameState スクリプトを作成する


 enum のみのスクリプトを作成します。
以前にも作成したことがありますので、復習になります。

 GameState は、あくまでも定義(枠組み)を作っているだけです。
列挙子として登録されている情報が、利用できる状態になっていることを示していますが、
「現在はどの列挙子であるのか」という情報は、ここでは管理出来ません。

 そのため、次の GameManager スクリプトを修正して、そちらに GameState 型の変数を作成して、
その GameState 型の変数が、現在の列挙子を管理することになります。


GameState.cs

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


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


GameManager スクリプトを修正する


 GameState 型の変数の宣言を追加し、この値として、GameState 型で定義した列挙子の値を1つだけ代入して利用します。
2つ以上の列挙子は同時に代入されないため、これにより、「現在のゲーム内の列挙子の値」を「ゲーム内のゲームの進行状態」を表す情報として利用します。

 変数とは、スクリプトを記述するエンジニアが、自分で運用する方法を決定し、それにまつわる名称を付けることになります。
そのイメージを持つようにすることで、設計した内容をプログラム化していくことが可能になります。

 合わせて、Start メソッドを修正し、GameState 型の変数に代入処理を行って、現在のゲームの進行状態を更新していきます。

 今回であれば、Start メソッドが開始されたタイミングで、currentGameState 変数を、準備中の状態にしています。
そのため、GameManager クラスに関わらず、currentGameState 変数を参照することにより、すべてのクラスにおいて、ゲームの進行状態を「準備中」であることを利用できます。
例えば、準備中の状態であるならば、特定の処理は行わない、といった機能を実装することが出来るようになります

 その後、Start メソッド内の処理がすべて終了したタイミングで、currentGameState 変数の値をプレイ・移動中の状態にしています。
これにより、currentGameState 変数は、ゲームが開始されたことを表現することになりますので、またそれに合わせた機能を作り出すことによって、
ゲームプレイ・移動中のみ許可される処理などを実装することが出来るようになります。

 なお、Start メソッド内には、次回以降で実装予定の処理を TODO で追記しています。
今後、どのような処理が追加されていくのかをイメージしておくことが大切です。

 自分で処理を組み立てるようになった場合にも、このように、今後追加しておきたい処理については、
こまめに TODO を残しておくようにするといいでしょう。



 なお、同様に GameState の切り替えの処理が StartMission メソッドと EndMission メソッドにおいても実装されています。
StartMission メソッドおいては currentGameState 変数の値をプレイ・移動中の状態からミッション中に変更し、
EndMission メソッド内においては currentGameState 変数の値をミッション中の状態からプレイ・移動中に変更しています。

 変数の切り替えをタイミングよく行っていくことで、ゲームの進行状態を GameManager スクリプトが管理しています。

 この実装方法は色々なゲームにおいても利用可能な処理になりますので、しっかりと学習しておいてください。


GameManager.cs

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



<WaitUntil クラス>


 WaitUntil クラスは、コルーチン内で命令できる待機処理です。yield return をつけて new(インスタンス)します

 WaitUntil クラスにはコンストラクタ・メソッドがあり、インスタンスされると、引数で指定した条件を満たすまで、処理を一時中断して待機させることが出来ます。

    // 経路の準備が完了するのを待つ
        yield return new WaitUntil(() => railMoveController.GetMoveSetting());

 今回の場合の条件は、【RailMoveController クラスに用意されている GetMoveSetting メソッドを毎フレーム実行し、その戻り値が true になったら】という条件を満たすことが必要になります。
RailMoveController クラス内にある tweenMove 変数が null でない場合に true の値が戻りますので、false の値は、この処理の場所で待機します。
戻り値が true になったら、処理は再度再開されて、次の処理に移ります。


参考サイト
Unity公式スクリプトリファレンス
WaitUntil
https://docs.unity3d.com/ja/current/ScriptReferenc...


GameManager ゲームオブジェクトの確認を行う


 新しい変数を追加しましたので、GameManager ゲームオブジェクトのインスペクターを確認します。

 enum 型の currentGameState 変数は、プルダウンメニューとして表示されます。


GameManager ゲームオブジェクト インスペクター画像



 こちらの currentGameState 変数の値もゲーム実行中にリアルタイムで変化しますので、デバッグを行う際にも活用してください。



RailMoveController スクリプトを修正する


 GameManager クラス内に追加された currentGameState 変数を利用して、特定の状態のみ、処理が行われるようにする機能を追加します。

 具体的には、currentGameState 変数の値が Play_Move の状態になるまで、カメラの移動を停止する機能を実装しています。
なぜそのような制御が必要になるのか、currentGameState 変数の切り替わるまでの処理の流れを確認しながら、考えてみてください。

 また、スクリプト内に処理の実装の確認を行う前に、自分で、どのタイミングに処理を追加すれば、今回実装したい処理、想定する処理になるのかを考えてみてください。
イメージを作って、実際に書いてみたりしながら処理を確認するようにすることで、ロジックを考えていく力を養うことが出来ます。


RailMoveController.cs

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




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


 すべての処理を実装しましたので、処理の内容を見直して、流れを把握してから、ゲームを実行してください。

 どのような処理が制御されて、ゲームの挙動が変わるのかを自分で理解してから確認を行うようにしましょう。

 今回の修正により、どのゲームオブジェクトのインスペクターを確認すればいいのか、
どのようになれば正しい制御になっていると言えるのか、といった部分を自分で説明できるようしてください。



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

 => 次は 手順18 ー武器用のデータベース作成ー です。