using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.AI; using System.Collections; using System.Collections.Generic; /// /// プレイヤーの共通ゲージ、時間停止(Codingモード)、UI、および各種バフの制限時間を管理するクラス /// public class PlayerStatusManager : MonoBehaviour { public static PlayerStatusManager Instance { get; private set; } [Header("Codingモード用 入力設定")] [SerializeField] private InputActionProperty zlButtonAction; [SerializeField] private InputActionProperty zrButtonAction; [Header("プレイヤー移動・操作制御用 入力設定")] [Tooltip("プレイヤーの移動入力(例: LeftHand Move)のアクションを指定してください")] [SerializeField] private InputActionProperty moveAction; [Tooltip("プレイヤーの視点回転入力(例: RightHand Turn)があれば指定してください(任意)")] [SerializeField] private InputActionProperty turnAction; [Header("ゲージ設定")] [SerializeField] private float maxGauge = 100f; [SerializeField] private float currentGauge = 0f; [Header("表示UI設定")] [Tooltip("画面全体を追従させる親オブジェクト(World Space Canvasや3D台座)を指定してください")] [SerializeField] private GameObject codingModeUI; [Header("バフパラメータ設定")] [Tooltip("攻撃力UP・防御力UPの持続時間 (秒)")] [SerializeField] private float buffDuration = 10f; [Tooltip("攻撃力UP時のダメージ倍率 (例: 1.5倍)")] [SerializeField] private float attackBuffMultiplier = 1.5f; [Tooltip("防御力UP時の被ダメージ軽減率 (例: 0.5ならダメージ50%カット)")] [SerializeField] private float defenseBuffMultiplier = 0.5f; [Tooltip("HP回復バフ発動時の回復量")] [SerializeField] private float hpHealAmount = 30f; // 各バフの残り時間を管理するタイマー(0より大きければバフ有効) private float attackBuffTimer = 0f; private float defenseBuffTimer = 0f; // 現在Codingモード(時間停止中)かどうかのフラグ private bool isCodingMode = false; // 【記憶リスト】一時停止させた敵のアニメーターとNavMeshAgentを記憶しておく private List pausedAnimators = new List(); private List pausedAgents = new List(); #region プロパティ public bool IsAttackBuffActive => attackBuffTimer > 0f; public bool IsDefenseBuffActive => defenseBuffTimer > 0f; public float CurrentAttackMultiplier => IsAttackBuffActive ? attackBuffMultiplier : 1.0f; public float CurrentDefenseMultiplier => IsDefenseBuffActive ? defenseBuffMultiplier : 1.0f; #endregion private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); } } private void OnEnable() { if (zlButtonAction.action != null) zlButtonAction.action.Enable(); if (zrButtonAction.action != null) zrButtonAction.action.Enable(); if (moveAction.action != null) moveAction.action.Enable(); if (turnAction.action != null) turnAction.action.Enable(); } private void OnDisable() { if (zlButtonAction.action != null) zlButtonAction.action.Disable(); if (zrButtonAction.action != null) zrButtonAction.action.Disable(); if (moveAction.action != null) moveAction.action.Disable(); if (turnAction.action != null) turnAction.action.Disable(); } private void Start() { if (codingModeUI != null) codingModeUI.SetActive(false); } private void Update() { CheckComboInput(); // ゲームプレイ中(時間停止中でないとき)のみ、バフのタイマーを減算する if (!isCodingMode) { UpdateBuffTimers(); } } public void AddGauge(float amount) { if (isCodingMode) return; currentGauge += amount; currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge); Debug.Log($"🔋 共通ゲージ増加: {currentGauge} / {maxGauge}"); } private void CheckComboInput() { if (zlButtonAction.action == null || zrButtonAction.action == null) return; bool zlPressed = zlButtonAction.action.triggered && zlButtonAction.action.ReadValue() > 0.5f; bool zrPressed = zrButtonAction.action.triggered && zrButtonAction.action.ReadValue() > 0.5f; // 同時押しの判定 bool isComboTriggered = (zlPressed && zrButtonAction.action.ReadValue() > 0.5f) || (zrPressed && zlButtonAction.action.ReadValue() > 0.5f); if (isComboTriggered) { if (!isCodingMode && currentGauge >= maxGauge) { // 通常時 ➔ ゲージ満タンならCodingモード発動 StartCodingMode(); } else if (isCodingMode) { // ★Codingモード中に再度同時押し ➔ キャンセルして無消費で復帰 CancelCodingMode(); } } } /// /// Codingモード(時間停止)を開始する /// private void StartCodingMode() { isCodingMode = true; // 1. プレイヤーの移動・視点回転の入力アクションを無効化(Disable)して足止めする if (moveAction.action != null) moveAction.action.Disable(); if (turnAction.action != null) turnAction.action.Disable(); // 2. シーン内の敵のアニメーターを検索して完全停止 Animator[] allAnimators = FindObjectsByType(FindObjectsSortMode.None); pausedAnimators.Clear(); foreach (var anim in allAnimators) { if (anim == null) continue; if (anim.gameObject == this.gameObject || anim.CompareTag("Player")) continue; anim.speed = 0f; pausedAnimators.Add(anim); } // 3. ボスのNavMeshAgent(自動移動)も一時停止させる NavMeshAgent[] allAgents = FindObjectsByType(FindObjectsSortMode.None); pausedAgents.Clear(); foreach (var agent in allAgents) { if (agent == null || !agent.enabled || !agent.gameObject.activeInHierarchy) continue; if (agent.CompareTag("Player")) continue; if (!agent.isStopped) { agent.isStopped = true; pausedAgents.Add(agent); } } if (codingModeUI != null) codingModeUI.SetActive(true); Debug.Log("⏳ Codingモード:プレイヤー移動をロック&敵の時間(アニメ・NavMesh)を完全停止しました。"); } /// /// バフを適用してゲームを再開する(ゲージ消費あり) /// public void ApplyBuffsAndResume(string buff1, string buff2) { // 1. 選択された2つのバフをそれぞれ発動 ActivateBuffByName(buff1); ActivateBuffByName(buff2); // 2. ゲーム状態を復帰(ゲージを消費) ResumeWorldState(consumeGauge: true); Debug.Log("▶ Codingモード完了:バフを適用してゲームを再開しました。"); } /// /// ★新規実装:Codingモードをキャンセルしてゲームを再開する(ゲージ消費なし) /// public void CancelCodingMode() { // ゲーム状態を復帰(ゲージは維持) ResumeWorldState(consumeGauge: false); Debug.Log("↩️ Codingモードキャンセル:ゲージを維持したまま通常状態に復帰しました。"); } /// /// 世界の状態(アニメーション・NavMesh・プレイヤー移動・UI)を復帰させる共通メソッド /// private void ResumeWorldState(bool consumeGauge) { // 1. 停止させていた敵のアニメーターを元の速度(1.0f)に戻す foreach (var anim in pausedAnimators) { if (anim != null) { anim.speed = 1f; } } pausedAnimators.Clear(); // 2. 停止させていたNavMeshAgentの移動を再開する foreach (var agent in pausedAgents) { if (agent != null && agent.enabled) { agent.isStopped = false; } } pausedAgents.Clear(); // 3. プレイヤーの移動・視点回転の入力アクションを再有効化(Enable)して操作ロックを解除 if (moveAction.action != null) moveAction.action.Enable(); if (turnAction.action != null) turnAction.action.Enable(); // 4. フラグとUIをリセット isCodingMode = false; if (codingModeUI != null) codingModeUI.SetActive(false); // 5. ゲージの消費制御 if (consumeGauge) { currentGauge = 0f; // バフ決定時のみゲージ消費 } } private void ActivateBuffByName(string buffName) { switch (buffName) { case "AttackUp": attackBuffTimer = buffDuration; Debug.Log($"⚔️ 攻撃力UPバフ発動! 倍率: {attackBuffMultiplier} / 効果時間: {buffDuration}秒"); break; case "DefenseUp": defenseBuffTimer = buffDuration; Debug.Log($"🛡️ 防御力UPバフ発動! 被ダメージ倍率: {defenseBuffMultiplier} / 効果時間: {buffDuration}秒"); break; case "Heal": ExecuteHeal(); break; default: Debug.LogWarning($"未定義のバフ名が検出されました: {buffName}"); break; } } private void ExecuteHeal() { Debug.Log($"💚 HP回復バフ発動! 回復量: {hpHealAmount}"); } private void UpdateBuffTimers() { if (attackBuffTimer > 0f) { attackBuffTimer -= Time.deltaTime; if (attackBuffTimer <= 0f) Debug.Log("⚔️ 攻撃力UPバフの効果が終了しました。"); } if (defenseBuffTimer > 0f) { defenseBuffTimer -= Time.deltaTime; if (defenseBuffTimer <= 0f) Debug.Log("🛡️ 防御力UPバフの効果が終了しました。"); } } }