1 / 5 状態遷移の仕様を決める
ゲーム全体の状態を整理し、遷移図と遷移表からGameStateを定義します。
ゲーム全体の状態を管理する
第07回までに、PlayerとEnemyがダメージを受け、HPが0になると死亡する処理を作りました。ゲームクリアとゲームオーバーは、まだ実装していません。
ゲームの勝敗を決めるには、Enemyの撃破数とPlayerのHPをまとめて判断する処理が必要です。今回は、その役割を持つGameManagerを実装します。
GameManagerには、ゲーム全体の進行状態を表すGameStateを持たせます。各オブジェクトから情報を受け取り、ゲームのルールに従って勝敗を決めるクラスです。
| 情報 | 発生元 | GameManagerの判断 |
|---|---|---|
| Enemyを1体倒した | Enemy | 撃破数を1増やす |
| 撃破数が目標へ達した | 撃破数 | ゲームクリアにする |
| PlayerのHPが0になった | DamageReceiver | ゲームオーバーにする |
GameManagerが扱うのは、ゲーム全体の進行状態です。Enemyの追跡やPlayerのHP計算は、各オブジェクトの処理として残します。GameManagerから直接操作することはありません。
ステートマシン
現在の状態に応じて、実行できる処理を決める仕組みがステートマシンです。状態はステート、ステートマシンは英語でState Machine、日本語で状態機械と呼びます。敵キャラクターやUIなど、ゲーム内の様々なオブジェクトを制御するのに適した重要な仕組みです。
今回のGameManagerもステートマシンとして実装し、ゲームの進行状態を管理します。
ステートマシンを作るときは、現在の状態、状態を切り替える条件、切り替え時の処理を決めます。今回はプレイ中に目標数の敵を倒すことが、勝利へ切り替える条件です。勝利に切り替わったら、入力や敵の行動を止めます。
第06回のEnemyStateとの比較
第06回のEnemyStateも、簡易なステートマシンの実装例です。1体のEnemyについて、待機、移動、攻撃、被弾、死亡のどの状態かを表していました。
今回のGameStateで表すのは、ゲーム全体の状態です。開始前、プレイ中、勝利、敗北のいずれかになります。
EnemyStateとGameStateは、別々のステートマシンです。ゲームプログラミングでは、このように複数のステートマシンを組み合わせて、複雑なゲームの進行を実現するのが基本です。
遷移図と遷移表から仕様を決める
コードを書く前に、ステートマシンの仕様を遷移図と遷移表で整理します。
| 構成要素 | 意味 | 今回の例 |
|---|---|---|
| 状態 | 現在どの段階にいるか | Ready、Playing、GameClear、GameOver |
| 遷移 | ある状態から別の状態へ切り替わること | PlayingからGameClearへ切り替わる |
| 遷移条件 | 遷移を許可する条件 | 撃破数が目標以上になる |
| 遷移時処理 | 状態が変わった瞬間に一度行う処理 | UIへ通知する、入力や敵の行動を止める |
| 現在状態 | 条件 | 次の状態 | 遷移時処理 |
|---|---|---|---|
Ready | Start()が呼ばれる | Playing | 開始を通知する |
Playing | 撃破数が目標以上 | GameClear | 生成停止、結果通知、入力と敵行動の停止 |
Playing | Playerが死亡 | GameOver | 生成停止、結果通知、入力と敵行動の停止 |
図を準備しています…
今回は、GameClearからPlayingへ直接戻る遷移を用意しません。再挑戦するときはGame Sceneを読み直します。この処理は次回作ります。
GameManagerは終了条件の通知を受け取ると、すぐに終了状態へ切り替わります。終了後の通知は受け付けません。そのため、同じフレームで複数の終了条件を満たした場合は、先に通知された結果を採用します。
GameStateで状態の候補を定義する
Assets/Scripts/GameState.csを作成します。
public enum GameState
{
Ready,
Playing,
GameClear,
GameOver
}Readyは開始前の状態です。GameManagerが生成されてからStart()の実行までが、この状態になります。Playingは勝敗の判定を受け付けるプレイ中の状態で、GameClearとGameOverは終了状態です。
enumは、状態の候補に名前を付けるために使います。今回のPlayingやGameClearが、その名前です。数値を覚えなくても、どの状態を代入・比較しているかをコードから読み取れます。
プレイ中にPlayerの死亡通知を受け、その後で目標撃破数に達した場合を、遷移表で追ってください。死亡通知を先に受けるので、最初にGameOverへ移ります。終了後の通知は受け付けないため、結果は敗北のままです。
-
Ready、Playing、GameClear、GameOverの役割と、許可する遷移を説明できる。