using UnityEngine; using DG.Tweening; public class CameraController : MonoBehaviour { [SerializeField] private Camera mainCamera; public void ClearCameraRoll(Vector3 pos, Vector3 rotation, float[] durations) { Sequence sequence = DOTween.Sequence(); sequence.Append(mainCamera.transform.DOMove(pos, durations[0]).SetEase(Ease.InQuart)); sequence.AppendInterval(0.5f); sequence.Append(mainCamera.transform.DORotate(rotation, durations[1]).SetEase(Ease.InQuart)); } }
using UnityEngine; /// <summary> /// 装備している武器の交換用クラス /// </summary> public class WeaponChanger : MonoBehaviour { public int currentWeaponNo; [SerializeField] private PlayerController player; [SerializeField] private WeaponDetail[] weapons; /// <summary> /// 初期武器のモデル表示。この処理は GameManager の Start メソッド内で命令を受けて実行します /// </summary> public void InitWeaponModel() { // 武器モデルの表示更新 SwitchWeaponModel(); } /// <summary> /// 武器の表示更新 /// </summary> private void SwitchWeaponModel() { // 武器の表示/非表示の切り替え for (int i = 0; i < weapons.Length; i++) { if (weapons[i].weaponNo == GameData.instance.weaponDatasList[currentWeaponNo].weaponNo) { weapons[i].gameObject.SetActive(true); } else { weapons[i].gameObject.SetActive(false); } } } void Update() { if (Input.GetKeyDown(KeyCode.L)) { // <= 任意のボタンに設定してください。 ChangeWeapon(); } } /// <summary> /// 武器の交換 /// </summary> public void ChangeWeapon() { // 初期武器しか所持していない場合 if (GameData.instance.weaponDatasList.Count <= 1) { Debug.Log("初期武器しかないため、交換しない"); // 武器交換しない return; } // 現在選択している武器の番号を加算 currentWeaponNo = ++currentWeaponNo % GameData.instance.weaponDatasList.Count; // 武器のデータを更新 player.ChangeBulletData(GameData.instance.weaponDatasList[currentWeaponNo]); // 武器モデルの表示更新 SwitchWeaponModel(); Debug.Log("武器交換"); } ////* 新しいメソッドを1つ追加します *//// /// <summary> /// すべての武器を非表示 /// </summary> public void InactiveWeapons() { for (int i = 0; i < weapons.Length; i++) { weapons[i].gameObject.SetActive(false); } } ////* ここまで *//// }
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// プレイヤー情報の管理クラス /// </summary> public class PlayerController : MonoBehaviour { private int hp; // 現在のHp値 private int bulletCount; // 現在の弾数値 [SerializeField, Header("最大Hp値")] private int maxHp; [SerializeField, Header("最大弾数値")] private int maxBullet; [SerializeField, Header("リロード時間")] private float reloadTime; [Header("弾の攻撃力")] public int bulletPower; [Header("弾の連射速度")] public float shootInterval; [Header("弾の射程距離")] public float shootRange; [Header("リロード機能のオン/オフ")] public bool isReloadModeOn; [Header("リロード状態の制御")] public bool isReloading; [SerializeField] private UIManager uiManagaer; public int currentWeaponNo; // 現在使用している武器の番号 [System.Serializable] public class BulletCountData { // 入れ子クラス public int bulletNo; // 武器の番号 public int bulletCount; // 武器の残弾数 /// <summary> /// 残弾数の更新 /// </summary> /// <param name="amount"></param> public void SetBulletCount(int amount) { bulletCount = amount; Debug.Log("残弾数更新"); } } public List<BulletCountData> bulletCountDatasList = new List<BulletCountData>(); /// <summary> /// 弾数用のプロパティ /// </summary> public int BulletCount { set => bulletCount = Mathf.Clamp(value, 0, maxBullet); get => bulletCount; } //HP も同じようにプロパティ化できますが、今回はしていません。挑戦してみてください。 ////* 変数の宣言を2つ、プロパティを1つ追加 *//// private bool isShootPermission; /// <summary> /// 発射許可用。true であれば発射できるようにする /// </summary> public bool IsShootPerimission { set => isShootPermission = value; get => isShootPermission; } [SerializeField] private GameObject playerObj; ////* ここまで *//// void Start() { // Debug 用 SetUpPlayer(); } /// <summary> /// プレイヤー情報の初期設定 /// </summary> public void SetUpPlayer() { // maxHp の設定があるか確認。なければ初期値 10 でセットして hp を設定 hp = maxHp = maxHp == 0 ? 10 : maxHp; // maxBullet の設定があるか確認。なければ初期値 10 でセットして 弾数を設定 BulletCount = maxBullet = maxBullet == 0 ? 10 : maxBullet; // UI にライフ用アイコンを最大HP数だけ生成する uiManager..SetPlayerInfo(maxHp); ////* ここから処理を追加 *//// // 武器の発射許可 IsShootPerimission = true; ////* ここまで *//// // TODO そのほかの初期設定があればここで行う } /// <summary> /// HPの計算と更新 /// </summary> public void CalcHp(int amount) { hp = Mathf.Clamp(hp += amount, 0, maxHp); // プロパティを作成してもいいです Debug.Log("現在のHp : " + hp); // UI で hp が確認できるようになったらコメントアウトします // HP 表示の更新 uiManagaer.UpdateDisplayLife(hp); if (hp <= 0) { Debug.Log("Game Over"); } } /// <summary> /// 弾数の計算と更新 /// </summary> /// <param name="amout"></param> public void CalcBulletCount(int amout) { BulletCount += amout; Debug.Log("現在の弾数 : " + BulletCount); // UI で弾数が確認できるようになったらコメントアウトします // TODO 弾数のUI表示更新 } /// <summary> /// 弾数のリロード /// </summary> public IEnumerator ReloadBullet() { // リロード状態にして、弾の発射を制御する isReloading = true; // リロード BulletCount = maxBullet; Debug.Log("リロード"); // UI で弾数が確認できるようになったらコメントアウトします // TODO 弾数のUI表示更新 // TODO SE // リロードの待機時間 yield return new WaitForSeconds(reloadTime); // 再度、弾が発射できる状態にする isReloading = false; } private void OnTriggerEnter(Collider other) { // TODO 敵からの攻撃によって被弾した場合の処理 // TODO ボスや敵の攻撃範囲を感知しないようにするためにタグでも判定するか、レイヤーを設定して回避する } /// <summary> /// 武器(バレット)の情報を変更して武器切り替え /// </summary> /// <param name="weaponData"></param> public void ChangeBulletData(WeaponData weaponData) { // 現在使用している武器の番号を保持 currentWeaponNo = weaponData.weaponNo; // 武器の情報を各変数に設定 bulletPower = weaponData.bulletPower; maxBullet = weaponData.maxBullet; reloadTime = weaponData.reloadTime; shootInterval = weaponData.shootInterval; shootRange = weaponData.shootRange; bulletCount = maxBullet; // すでに使用したことのある武器である場合 if (bulletCountDatasList.Exists(x => x.bulletNo == currentWeaponNo)) { // 弾数を前回の残弾数にする bulletCount = bulletCountDatasList.Find(x => x.bulletNo == currentWeaponNo).bulletCount; } } /// <summary> /// 使用している武器のデータ(武器の番号と残弾数)を記録して更新 /// </summary> /// <param name="weaponData"></param> public void UpdateCurrentBulletCountData(WeaponData weaponData) { // まだ一度も使用している武器の残弾数を記録していないとき if (!bulletCountDatasList.Exists(x => x.bulletNo == currentWeaponNo)) { // 新しくデータを作成して、記録 bulletCountDatasList.Add(new BulletCountData { bulletNo = currentWeaponNo, bulletCount = bulletCount }); } else { // 使用したことがある武器ですでにデータがある場合には、そのデータを見つけて上書きして記録 bulletCountDatasList.Find(x => x.bulletNo == currentWeaponNo).SetBulletCount(bulletCount); } // 武器の情報を設定 ChangeBulletData(weaponData); } ////* ここからメソッドを1つ追加 *//// /// <summary> /// ゲームクリア時の演出の準備 /// </summary> public void PrepareClearSettings() { // 発射許可を取り消し IsShootPerimission = false; // プレイヤーのゲームオブジェクトとの親子関係の解消 => カメラとプレイヤーとが別々になるので、カメラを動かすとカメラだけ動く playerObj.transform.SetParent(null); } ////* ここまで *//// }
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; [SerializeField] private UIManager uiManager; [SerializeField] private WeaponChanger weaponChanger; ////* ここから変数の宣言を1つ追加 *//// [SerializeField] private CameraController cameraController; ////* ここまで *//// private IEnumerator Start() { // ゲームの状態を準備中にする currentGameState = GameState.Wait; // ルート用の経路情報を設定 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]); // 初期武器のモデル表示 weaponChanger.InitWeaponModel(); // 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); } /// <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("ゲーム終了"); ////* 処理を追加します *//// // プレイヤー側のクリアの準備 playerController.PrepareClearSettings(); // すべての武器を非表示 weaponChanger.InactiveWeapons(); // カメラの演出 cameraController.ClearCameraRoll(playerController.transform.position + new Vector3(0, 0, 10), new Vector3(0, 180, 0), new float[2] { 1.5f, 2.0f }); ////* ここまで *//// yield break; } // ルートに分岐があるかどうかの判定 if (DataBaseManager.instance.GetBranchDatasListCount(nextStagePathDataNo) == 1) { Debug.Log("分岐なしで次のルートへ"); // 分岐なしの場合、次の経路を登録 originRailPathData = DataBaseManager.instance.GetRailPathDatasFromBranchNo(nextStagePathDataNo, BranchDirectionType.NoBranch); } else { // 分岐がある場合、UI に分岐を表示し、選択を待つ Debug.Log("ルートの分岐発生"); // 分岐がある場合、分岐イベントを発生させて、画面上に矢印のボタンを表示 uiManager.GenerateBranchButtons(DataBaseManager.instance.GetBranchDirectionTypes(nextStagePathDataNo)); // 分岐を選択するまで待機(while でもOK) yield return new WaitUntil(() => uiManager.GetSubmitBranch().Item1 == true); // 選択した分岐のルートを設定 originRailPathData = DataBaseManager.instance.GetRailPathDatasFromBranchNo(nextStagePathDataNo, uiManager.GetSubmitBranch().Item2); } // ルート内のミッション情報を設定 SetMissionTriggers(); // 経路を移動先に設定 railMoveController.SetNextRailPathData(originRailPathData); // レール移動の経路と移動登録が完了するまで待機 yield return new WaitUntil(() => railMoveController.GetMoveSetting()); // ゲームの進行状態を移動中に変更する currentGameState = GameState.Play_Move; } }