Unityに関連する記事です

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

手順24 ーゲームの進行管理の制御機能の実装 
42.GameState の作成し、GameManager と CharaGenerator を修正して、GameState の運用を行ってゲームの進行管理をする機能を追加する



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

 ・enum を利用したステート管理の方法



42.GameState の作成し、GameManager と CharaGenerator を修正して、GameState の運用を行ってゲームの進行管理をする機能を追加する

1.設計


 ゲーム内のゲームオブジェクトが増えてくると同時に、ゲーム内の進行状態を管理する必要性が生まれてきます。
今回のゲームのシステムであれば、エネミーが配置されるよりも前に防衛用のキャラをたくさん配置できてしまうと、ゲームが成り立たなくなります。
また、ゲームクリアの状態になってもキャラを配置できてしまっても不要な操作になってしまうため、ゲーム全体の処理が備わってくるタイミングに合わせて
ゲームの状態と、その状態をつかってゲームの進行を管理していく要素が不可欠になります。
 
 この手順では、enum を活用して、GameState を作成し、この中に事前にゲームの状態として発生しえるものを列挙子として登録しておきます。
それを GameManager などのゲームを管理しているクラス内に、新しく GameState 型の変数を1つ宣言し、この変数が現在のゲームの進行状態を管理するように役割を与えます。

 こちらは参考例です。
列挙子は日本語でも登録可能です。ただし、見た目は文字列に見えますが、文字列ではありませんので注意してください。

    /// <summary>
    /// ゲームの状態
    /// </summary>
    public enum GameState {
        Preparate,       // ゲーム開始前の準備中
        Play,            // ゲームプレイ中
        Stop,            // ゲーム内の処理の一時停止中
        GameUp           // ゲーム終了(ゲームオーバー、クリア両方)
    }

 この情報を、1つのクラス・1つの変数によってゲーム全体の進行管理を行うイメージをしてみてください。
この設計をすることにより、常に、このクラスの GameState 型の変数を確認することで、各クラスがどのような状態のときに、どんな制御を行うようにするかを考えてみましょう。

 例えば、CharaGenerator クラスであれば、ゲームの現在の状態が「プレイ中」であるときにだけ、画面をタップした際にキャラの配置用のポップアップを開くようにする、という感じです。
これは GameManager クラスの GameState 型の変数を参照することで、ゲームの現在の状態が「プレイ中」であるときを確認すればよい形になります。


2.GameManager スクリプトを修正し、GameState を追加する


 enum の GameState については、今回は GameManager クラス内に宣言をして作成しています。これは、enum のみを1つのファイルとして作成してもいいです。

 GameState 型の enum にはあらかじめ、自分で想定しているゲームの進行状態を登録しておきます。
4つの状態を列挙子として定義し、その状態の1つの状態を管理できるように、GameState 型の currentGameState 変数も宣言して管理します。
そのため、ゲームの進行状態を確認したい場合には、この currentGameState 変数を参照することで確認ができる設計になっています。

 この情報を使って、ロジックを作成していくことが、この手順の目標になります。


GameManager.cs


 スクリプトを修正したらセーブをします。


3.CharaGenerator スクリプトを修正する


 GameManager に用意した currentGameState 変数の情報を参照して、この値が GameState.Play であるときだけ、キャラの配置が可能になるように制御を加えます。


CharaGenerator.cs

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


 スクリプトを修正したらセーブします。


4.<enum を利用したステート管理の方法>


 enum(列挙型) を条件式の判定式に利用するためには、定義している情報を使います。


// 画面をタップ(マウスクリック)し、かつ、配置キャラポップアップが非表示状態、かつ、ゲームの現在の進行状態が Play なら
if (Input.GetMouseButtonDown(0) && !placementCharaSelectPopUp.gameObject.activeSelf && gameManager.currentGameState == GameManager.GameState.Play) {

 比較条件の部分だけを取り出して見ていきます。

gameManager.currentGameState == GameManager.GameState.Play  //  ← クラス名.列挙型名.列挙子の並び

 このとき、下記のように記述するとエラーになります。

gameManager.currentGameState == gameManager.GameState.Play   //  ← 変数名.列挙型名.列挙子の並び

 このエラーの理由を解説します。



 このケースの場合、currentGameState 変数の型が GameState 型です。
enum 型の情報を比較する場合、その定義をどこで作成しているかを確認します。

 今回の GameState 型は GameManager クラス内で定義されています。

public class GameManager : MonoBehaviour {}

    public enum GameState {  // ← ここ
    (列挙子)
   }

}

 このような状態です。
この場合、他のクラスメンバーと同じで、この GameState 型は、「GameManager」クラス内部の情報として扱われます。
つまり、GameManager クラスの管理下です。よって、この GameState 型を、比較の対象として使う場合には、
その管理元である、GameManager の元で使う、という書式で書く必要があります。

 このとき、いずれかの変数に代入されている GameManager 型では定義そのものを使えません

 今回の gameManager は、変数です。
これは、GameMangaer 型の情報を代入できる変数ですが、クラスのインスタンスの参照を代入しているものであって、
この変数からは、条件式の比較用の定義である GameState 型は利用できません

 あくまでも、GameState 型の定義を使う場合には、GameState 型を定義したクラスの名前をそのまま書いて利用する必要があります。

 そのため、先ほどのように変数を参照した書式で書いてしまうと

gameManager.currentGameState == gameManager.GameState.Play   //  ← 変数名.列挙型名.列挙子の並び

 GameState 型の定義は利用できないため、エラーになります。



 列挙型はファイルを分けると、処理のイメージが作りやすくなります。

 この enum の GameState の定義を、GameManager クラスの外側に移動させてみてください。
あるいは、新しいスクリプト・ファイルを作成し、そちらに移動させてみてください。

<GameManager スクリプト内で GameState をクラス外部へ移動させた場合>
using 〜;

public enum GameState {  // ← ここに移動
  (列挙子)
}

public class GameManager : MonoBehaviour {}

}



<新しくスクリプト・ファイルを作成した場合>
public enum GameState {

}

 このように定義すると、GameState 型は、GameManager クラスの管理下ではなく、単体の情報として定義出来るようになります。
この場合、GameManager との関連性はなくなります

 先ほどの条件式は

gameManager.currentGameState== GameState.Play

 上記のように GameManager クラスを書かずに定義として利用できる状態になります。
こうすることで、enum の定義は、変数経由で参照する情報でない、ということが見えてきます。
 
 gameManager.GameState.Play と書く場合、最初の gameManager 変数から参照して使う、という書式になりますが、
enum の定義自体は、変数から参照して使う情報ではないので、こういった使い方は出来ない、ということになります。



 もしも上記のように GameState 型をクラスの外で定義すると、GameManager.GameState と書いている部分でエラーが出ます。
GameManager クラスの管理下からいなくなったためです。

 そのため、確認後は戻しておいてください。
あるいは、全部の書式を【列挙型名.列挙子】[GameState.Play] のように、最初に書いている GameManager クラスの部分を削除すればエラーは消えます。


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


 GameState によってゲームの現在の状態を管理する機能が実装されました。
これによって、各クラスはこの情報を参照することによって制限が行われるようにしていく必要があります。
どうすれば制御の処理になるのか、ロジックを思い浮かべながら処理を考えていきましょう。

 今回は画面のタップによるキャラ配置ポップアップの生成のタイミングを制限しています。

 GameState が Play に切り替わる前は画面をタップしてもポップアップが表示されてなくなっていれば制御成功です。

 また今後、GameState が Play ではなくなった際にも、この制御処理によってポップアップが表示されなくなります。
例えば、GameState が GameUp の状態になって、ゲームが終了した状態になった場合などです。
この場合も GameState は Play ではありませんので、ポップアップが表示されなくなります。

 用意した情報をどのように活用することができればいいのか、処理の全体を俯瞰的に考えてロジックを組んでいくことが大切になります。



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

 次は 手順25 −ゲームの進行管理の制御機能の実装◆ です。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます