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
<= クリックすると開きます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour {
[SerializeField]
private RailMoveController railMoveController;
[SerializeField, Header("経路用のパス群の元データ")]
private RailPathData originRailPathData; // 後程 List 化して複数のルートを管理できるようにします
[SerializeField, Header("パスにおけるミッションの発生有無")] // Debug 用
private bool[] isMissionTriggers;
[SerializeField]
private PlayerController playerController;
[SerializeField]
private EventGenerator eventGenerator;
[SerializeField, Header("ミッションで発生している敵のリスト")]
private List<EnemyController> enemiesList = new List<EnemyController>();
private int currentMissionDuration;
////* ここから変数の宣言を1つ追加。 *////
[Header("現在のゲームの進行状態")]
public GameState currentGameState;
private IEnumerator Start() { // <= ☆ 戻り値を void から IEnumerator 型に変更し、コルーチンメソッドにします。
////* ここまで *////
////* ここから TODO を追加 *////
// ゲームの状態を準備中にする
currentGameState = GameState.Wait;
////* ここまで *////
// TODO ルート用の経路情報を設定
// イベント生成機能の準備
eventGenerator.SetUpEventGenerator(this, playerController);
////* ここから次回以降に実装予定の TODO を追加 *////
// TODO 初期武器登録
// TODO 武器取得イベント用の設定
// TODO 初期武器設定
////* ここまで *////
// RailMoveController の初期設定
railMoveController.SetUpRailMoveController(this);
// パスデータよりミッションの発生有無情報取得
SetMissionTriggers();
// 次に再生するレール移動の目的地と経路のパスを設定
railMoveController.SetNextRailPathData(originRailPathData);
////* ここから TODO を実装 *////
// 経路の準備が完了するのを待つ(この機能を利用するため、Start メソッドの戻り値を IEnumerator に変更してコルーチンメソッドに変えています)
yield return new WaitUntil(() => railMoveController.GetMoveSetting());
// ゲームの状態をプレイ中に変更する
currentGameState = GameState.Play_Move;
////* ここまで *////
}
/// <summary>
/// パスデータよりミッションの発生有無情報取得
/// </summary>
private void SetMissionTriggers() {
// 配列の初期化
isMissionTriggers = new bool[originRailPathData.GetIsMissionTriggers().Length];
// ミッション発生有無の情報を登録
isMissionTriggers = originRailPathData.GetIsMissionTriggers();
}
/// <summary>
/// ミッションの発生有無の判定
/// </summary>
/// <param name="index"></param>
public void CheckMissionTrigger(int index) {
if (isMissionTriggers[index]) {
// ミッション発生
PreparateMission(originRailPathData.pathDataDetails[index].missionEventDetail);
Debug.Log("ミッション発生");
} else {
// ミッションなし。次のパスへ移動を再開
railMoveController.CountUp();
}
}
/// <summary>
/// ミッションの準備
/// </summary>
/// <param name="missionEventDetail"></param>
private void PreparateMission(MissionEventDetail missionEventDetail) {
// ミッションの時間設定
currentMissionDuration = missionEventDetail.missionDuration;
// TODO 武器取得イベントか判定
// ミッション内の各イベントの生成(敵、ギミック、トラップ、アイテムなどを生成)
eventGenerator.PrepareGenerateEnemies(missionEventDetail.enemyPrefabs, missionEventDetail.eventTrans);
// ミッション開始
StartCoroutine(StartMission(missionEventDetail.clearConditionsType));
}
/// <summary>
/// ミッション開始
/// </summary>
/// <param name="clearConditionsType"></param>
/// <returns></returns>
private IEnumerator StartMission(ClearConditionsType clearConditionsType) {
////* ここから処理を追加 *////
// ゲームの進行状態をミッション中に変更
currentGameState = GameState.Play_Mission;
////* ここまで *////
// ミッションの監視
yield return StartCoroutine(ObservateMission(clearConditionsType));
// ミッション終了
EndMission();
}
/// <summary>
/// ミッションの監視
/// 各イベントの状態を監視
/// </summary>
/// <param name="clearConditionsType"></param>
/// <returns></returns>
private IEnumerator ObservateMission(ClearConditionsType clearConditionsType) {
// クリア条件を満たすまで監視(currentMissionDuration 変数には、敵の数か、残り時間が入る)
while (currentMissionDuration > 0) {
// クリア条件が時間経過の場合
if (clearConditionsType == ClearConditionsType.TimeUp) {
// カウントダウン
currentMissionDuration--;
}
// TODO 武器取得イベントかつ、武器選択のいずれかのボタンを押したら
yield return null;
}
Debug.Log("ミッション終了");
}
/// <summary>
/// ミッション終了
/// </summary>
public void EndMission() {
// TODO 武器の取得イベントの場合には武器を取得せずにポップアップを閉じる
// 今回分の敵の情報をクリア
ClearEnemiesList();
////* ここから処理を追加 *////
// ゲームの進行状態を移動中に変更
currentGameState = GameState.Play_Move;
////* ここまで *////
// カメラの移動再開
railMoveController.CountUp();
}
/// <summary>
/// 敵の List をクリア
/// </summary>
private void ClearEnemiesList() {
if (enemiesList.Count > 0) {
for (int i = 0; i < enemiesList.Count; i++) {
Destroy(enemiesList[i]);
}
}
enemiesList.Clear();
}
/// <summary>
/// 敵の情報を List から削除し、ミッション内の敵の残数を減らす
/// </summary>
/// <param name="enemy"></param>
public void RemoveEnemyList(EnemyController enemy) {
currentMissionDuration--;
enemiesList.Remove(enemy);
}
/// <summary>
/// 敵の情報をリストに追加
/// </summary>
/// <param name="enemy"></param>
public void AddEnemyList(EnemyController enemy) {
enemiesList.Add(enemy);
}
}