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; [Header("現在のゲームの進行状態")] public GameState currentGameState; [SerializeField] private WeaponEventInfo weaponEventInfo; private IEnumerator Start() { // ゲームの状態を準備中にする currentGameState = GameState.Wait; ////* TODO の実装 *//// // ルート用の経路情報を設定 originRailPathData = DataBaseManager.instance.GetRailPathDatasFromBranchNo(0, BranchDirectionType.NoBranch); ////* ここまで *//// // イベント生成機能の準備 eventGenerator.SetUpEventGenerator(this, playerController); // 初期武器登録 GameData.instance.AddWeaponData(DataBaseManager.instance.GetWeaponData(0)); // 武器取得イベント用の設定 weaponEventInfo.InitializeWeaponEventInfo(); // 初期武器設定 playerController.ChangeBulletData(GameData.instance.weaponDatasList[0]); // RailMoveController の初期設定 railMoveController.SetUpRailMoveController(this); // パスデータよりミッションの発生有無情報取得 SetMissionTriggers(); // 次に再生するレール移動の目的地と経路のパスを設定 railMoveController.SetNextRailPathData(originRailPathData); // 経路の準備が完了するのを待つ 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; // 武器取得イベントか判定 if (missionEventDetail.eventTypes[0] == EventType.Weapon) { // 武器の情報を取得してセット weaponEventInfo.SetWeaponData(DataBaseManager.instance.GetWeaponData(missionEventDetail.eventNos[0])); weaponEventInfo.Show(); } else { // ミッション内の各イベントの生成(敵、ギミック、トラップ、アイテムなどを生成) 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--; } // 武器取得イベントかつ、武器選択のいずれかのボタンを押したら if (weaponEventInfo.gameObject.activeSelf && weaponEventInfo.isChooseWeapon) { // イベント終了 currentMissionDuration = 0; weaponEventInfo.Hide(); Debug.Log("武器取得イベント終了"); yield break; } yield return null; } Debug.Log("ミッション終了"); } /// <summary> /// ミッション終了 /// </summary> public void EndMission() { // 武器の取得イベントの場合には武器を取得せずにポップアップを閉じる if (weaponEventInfo.gameObject.activeSelf) { weaponEventInfo.Hide(); } // 今回分の敵の情報をクリア 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); } ////* 新しくメソッドを2つ追加 *//// /// <summary> /// ルートの分岐確認の準備 /// </summary> /// <param name="nextbranchNo">moveCount</param> public void PreparateCheckNextBranch(int nextbranchNo) { StartCoroutine(CheckNextBranch(nextbranchNo)); } /// <summary> /// ルートの分岐判定 /// </summary> /// <param name="nextStagePathDataNo"></param> /// <returns></returns> private IEnumerator CheckNextBranch(int nextStagePathDataNo) { if (nextStagePathDataNo >= DataBaseManager.instance.GetStagePathDetasListCount()) { // 終了 Debug.Log("ゲーム終了"); yield break; } // ルートに分岐があるかどうかの判定 if (DataBaseManager.instance.GetBranchDatasListCount(nextStagePathDataNo) == 1) { Debug.Log("分岐なしで次のルートへ"); // 分岐なしの場合、次の経路を登録 originRailPathData = DataBaseManager.instance.GetRailPathDatasFromBranchNo(nextStagePathDataNo, BranchDirectionType.NoBranch); } else { // 分岐がある場合、UI に分岐を表示し、選択を待つ Debug.Log("ルートの分岐発生"); // TODO 分岐がある場合、分岐イベントを発生させて、画面上に矢印のボタンを表示 // TODO 分岐を選択するまで待機(while でもOK) // TODO 選択した分岐のルートを設定 } // ルート内のミッション情報を設定 SetMissionTriggers(); // 経路を移動先に設定 railMoveController.SetNextRailPathData(originRailPathData); // レール移動の経路と移動登録が完了するまで待機 yield return new WaitUntil(() => railMoveController.GetMoveSetting()); // ゲームの進行状態を移動中に変更する currentGameState = GameState.Play_Move; } ////* ここまで *//// }
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using System.Linq; public class RailMoveController : MonoBehaviour { [SerializeField] private Transform railMoveTarget; [SerializeField] private RailPathData currentRailPathData; private Tween tweenMove; private Tween tweenRotation; private Vector3[] paths; private float[] moveDurations; private int pathCount; private GameManager gameManager; ////* 新しい変数の宣言を1つ追加 *//// private int moveCount; ////* ここまで *//// /// <summary> /// RailMoveController の初期設定 /// </summary> /// <param name="gameManager"></param> public void SetUpRailMoveController(GameManager gameManager) { // <= GameManager より呼び出されます this.gameManager = gameManager; // TODO 他にもある場合には追記。必要に応じて引数を通じて外部から情報をもらうようにする } /// <summary> /// 次に再生するレール移動の目的地と経路のパスを取得して設定 /// </summary> /// <param name="nextPathDataList"></param> public void SetNextRailPathData(RailPathData nextRailPathData) { // <= GameManager より呼び出されます // 目的地取得 currentRailPathData = nextRailPathData; ; // 移動開始 StartCoroutine(StartRailMove()); } /// <summary> /// レール移動の開始 /// </summary> /// <returns></returns> public IEnumerator StartRailMove() { yield return null; // パスのカウントを初期化 pathCount = 0; ////* 処理のリファクタリング いままでの処理をコメントアウトします *//// // 移動する地点を取得するための配列の初期化 //paths = new Vector3[currentRailPathData.GetPathTrans().Length]; //float totalTime = 0; // 移動する位置情報と時間を順番に配列に取得 //for (int i = 0; i < currentRailPathData.GetPathTrans().Length; i++) { // paths[i] = currentRailPathData.GetPathTrans()[i].position; // totalTime += currentRailPathData.GetRailMoveDurations()[i]; //} // 上記の処理を以下の処理に書き換えます // // 移動する地点を取得するための配列の初期化と情報の取得 paths = currentRailPathData.GetPathTrans().Select(x => x.position).ToArray(); // 移動先のパスの移動時間を合計 float totalTime = currentRailPathData.GetRailMoveDurations().Sum(); ////* ここまで *//// // 各パスごとの移動時間を取得 moveDurations = currentRailPathData.GetRailMoveDurations(); // パスによる移動開始 RailMove(); // 移動を一時停止 PauseMove(); // ゲームの進行状態が移動中になるまで待機 yield return new WaitUntil(() => gameManager.currentGameState == GameState.Play_Move); // 移動開始 ResumeMove(); Debug.Log("移動開始"); } /// <summary> /// レール移動の一時停止 /// </summary> public void PauseMove() { // 一時停止 tweenMove.Pause(); tweenRotation.Pause(); } /// <summary> /// レール移動の再開 /// </summary> public void ResumeMove() { // 移動再開 tweenMove.Play(); tweenRotation.Play(); } /// <summary> /// パスのカウントアップ(パスごとに動かす場合) /// </summary> public void CountUp() { pathCount++; Debug.Log(pathCount); // 移動 RailMove(); } /// <summary> /// 2点間のパスの目標地点を設定して移動 /// </summary> public void RailMove() { // 残っているパスがない場合 if (pathCount >= currentRailPathData.GetPathTrans().Length) { // DOTween を停止 tweenMove.Kill(); tweenMove = null; tweenRotation = null; ////* TODO の実装 *//// // 移動完了に伴い、移動回数をカウントアップ moveCount++; // 移動先の確認。移動先が残っていない場合には、ゲームマネージャー側で分岐の確認(次のルート選定、移動先の分岐、ボス、クリアのいずれか) gameManager.PreparateCheckNextBranch(moveCount); ////* ここまで *//// Debug.Log("分岐確認"); return; } // パスの設定用の配列を宣言 Vector3[] targetPaths; // パスのカウント数に応じて分岐してパスを設定 if (pathCount == 0) { targetPaths = new Vector3[2] { railMoveTarget.position, paths[pathCount] }; } else { targetPaths = new Vector3[2] { paths[pathCount - 1], paths[pathCount] }; } // パスの移動時間を設定 float duration = moveDurations[pathCount]; Debug.Log("スタート地点 :" + targetPaths[0]); Debug.Log("目標地点 :" + targetPaths[1]); Debug.Log("移動にかかる時間 :" + duration); // パスの移動 tweenMove = railMoveTarget.transform.DOPath(targetPaths, duration, pathType).SetEase(Ease.Linear).OnWaypointChange((waypointIndex) => CheckArrivalDestination(waypointIndex)); // カメラの回転 tweenRotation = railMoveTarget.transform.DORotate(currentRailPathData.pathDataDetails[pathCount].pathTran.eulerAngles, duration).SetEase(Ease.Linear); Debug.Log($" 回転角度 : {currentRailPathData.pathDataDetails[pathCount].pathTran.eulerAngles} "); } /// <summary> /// パスの目標地点に到着するたびに実行される /// </summary> /// <param name="waypointIndex"></param> private void CheckArrivalDestination(int waypointIndex) { if (waypointIndex == 0) { return; } Debug.Log("目標地点 到着 : " + pathCount + " 番目"); // 移動の一時停止 PauseMove(); // ミッションがあるか確認(ミッションが発生するかゲームマネージャー側で判定を行う) gameManager.CheckMissionTrigger(pathCount); // Debug用 次のパスをセットして移動を実行 //CountUp(); } /// <summary> /// 移動用の処理が登録されたか確認 /// </summary> /// <returns></returns> public bool GetMoveSetting() { return tweenMove != null ? true : false; } }