Files
VRProject/Assets/_Scripts/PlayerStatusManager.cs
2026-07-21 12:28:09 +09:00

285 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.AI;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// プレイヤーの共通ゲージ、時間停止Codingモード、UI、および各種バフの制限時間を管理するクラス
/// </summary>
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<Animator> pausedAnimators = new List<Animator>();
private List<NavMeshAgent> pausedAgents = new List<NavMeshAgent>();
#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<float>() > 0.5f;
bool zrPressed = zrButtonAction.action.triggered && zrButtonAction.action.ReadValue<float>() > 0.5f;
// 同時押しの判定
bool isComboTriggered = (zlPressed && zrButtonAction.action.ReadValue<float>() > 0.5f) ||
(zrPressed && zlButtonAction.action.ReadValue<float>() > 0.5f);
if (isComboTriggered)
{
if (!isCodingMode && currentGauge >= maxGauge)
{
// 通常時 ➔ ゲージ満タンならCodingモード発動
StartCodingMode();
}
else if (isCodingMode)
{
// ★Codingモード中に再度同時押し ➔ キャンセルして無消費で復帰
CancelCodingMode();
}
}
}
/// <summary>
/// Codingモード時間停止を開始する
/// </summary>
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<Animator>(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<NavMeshAgent>(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を完全停止しました。");
}
/// <summary>
/// バフを適用してゲームを再開する(ゲージ消費あり)
/// </summary>
public void ApplyBuffsAndResume(string buff1, string buff2)
{
// 1. 選択された2つのバフをそれぞれ発動
ActivateBuffByName(buff1);
ActivateBuffByName(buff2);
// 2. ゲーム状態を復帰(ゲージを消費)
ResumeWorldState(consumeGauge: true);
Debug.Log("▶ Codingモード完了バフを適用してゲームを再開しました。");
}
/// <summary>
/// ★新規実装Codingモードをキャンセルしてゲームを再開するゲージ消費なし
/// </summary>
public void CancelCodingMode()
{
// ゲーム状態を復帰(ゲージは維持)
ResumeWorldState(consumeGauge: false);
Debug.Log("↩️ Codingモードキャンセルゲージを維持したまま通常状態に復帰しました。");
}
/// <summary>
/// 世界の状態アニメーション・NavMesh・プレイヤー移動・UIを復帰させる共通メソッド
/// </summary>
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バフの効果が終了しました。");
}
}
}