Files
VRProject/Assets/_Scripts/PlayerStatusManager.cs
ohgushiyuga 2f47302b9e Hpbar
2026-07-22 16:20:19 +09:00

244 lines
8.2 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.Generic;
/// <summary>
/// プレイヤーの共通ゲージ、時間停止Codingモード、UI、および各種バフの制限時間を管理するクラス
/// </summary>
public class PlayerStatusManager : MonoBehaviour
{
public static PlayerStatusManager Instance { get; private set; }
[Header("デバッグ設定")]
[Tooltip("チェックを入れると、ゲージが溜まっていなくてもZLZRでCodingModeを開けますテスト用")]
[SerializeField] private bool ignoreGaugeForDebug = true;
[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("パズル制限時間設定")]
[Tooltip("CodingModeパズルの制限時間")]
[SerializeField] private float codingLimitDuration = 15f;
private float codingTimer = 0f;
[Header("ゲージ設定")]
[SerializeField] private float maxGauge = 100f;
[SerializeField] private float currentGauge = 0f;
[Header("表示UI設定")]
[SerializeField] private GameObject codingModeUI;
[SerializeField] private PuzzleGridBoard puzzleBoard; // 盤面参照
[Header("バフパラメータ設定")]
[SerializeField] private float buffDuration = 10f;
[SerializeField] private float attackBuffMultiplier = 1.5f;
[SerializeField] private float defenseBuffMultiplier = 0.5f;
[SerializeField] private float hpHealAmount = 30f;
private float attackBuffTimer = 0f;
private float defenseBuffTimer = 0f;
private bool isCodingMode = false;
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()
{
EnableAction(zlButtonAction);
EnableAction(zrButtonAction);
EnableAction(moveAction);
EnableAction(turnAction);
}
private void OnDisable()
{
DisableAction(zlButtonAction);
DisableAction(zrButtonAction);
DisableAction(moveAction);
DisableAction(turnAction);
}
private void EnableAction(InputActionProperty property)
{
if (property.action != null) property.action.Enable();
}
private void DisableAction(InputActionProperty property)
{
if (property.action != null) property.action.Disable();
}
private void Start()
{
if (codingModeUI != null) codingModeUI.SetActive(false);
}
private void Update()
{
CheckComboInput();
if (!isCodingMode)
{
UpdateBuffTimers();
}
else
{
// CodingMode中の制限時間カウントダウン
codingTimer -= Time.deltaTime;
if (codingTimer <= 0f)
{
FailCodingModeByTimeout();
}
}
}
public void AddGauge(float amount)
{
if (isCodingMode) return;
currentGauge += amount;
currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge);
}
private void CheckComboInput()
{
if (zlButtonAction.action == null || zrButtonAction.action == null) return;
// 入力値の読み取り
float zlVal = zlButtonAction.action.ReadValue<float>();
float zrVal = zrButtonAction.action.ReadValue<float>();
bool zlPressed = zlButtonAction.action.triggered || zlVal > 0.5f;
bool zrPressed = zrButtonAction.action.triggered || zrVal > 0.5f;
// 両方のトリガーが引かれているか
bool isBothHeld = zlVal > 0.5f && zrVal > 0.5f;
bool isAnyTriggered = zlButtonAction.action.triggered || zrButtonAction.action.triggered;
if (isBothHeld && isAnyTriggered)
{
if (!isCodingMode)
{
// ゲージチェックデバッグフラグがONならゲージ無視で起動
if (ignoreGaugeForDebug || currentGauge >= maxGauge)
{
StartCodingMode();
}
else
{
Debug.LogWarning($"⚠️ ゲージが足りないためCodingModeを開けません。現在: {currentGauge} / 必要: {maxGauge}");
}
}
else
{
// CodingMode中に再度同時押し ➔ キャンセルして無消費で復帰
CancelCodingMode();
}
}
}
private void StartCodingMode()
{
isCodingMode = true;
codingTimer = codingLimitDuration;
if (puzzleBoard != null) puzzleBoard.ClearBoard();
DisableAction(moveAction);
DisableAction(turnAction);
// 敵のアニメーション・NavMesh停止
foreach (var anim in FindObjectsByType<Animator>(FindObjectsSortMode.None))
{
if (anim == null || anim.gameObject == this.gameObject || anim.CompareTag("Player")) continue;
anim.speed = 0f;
pausedAnimators.Add(anim);
}
foreach (var agent in FindObjectsByType<NavMeshAgent>(FindObjectsSortMode.None))
{
if (agent == null || !agent.enabled || !agent.gameObject.activeInHierarchy || agent.CompareTag("Player")) continue;
if (!agent.isStopped) { agent.isStopped = true; pausedAgents.Add(agent); }
}
if (codingModeUI != null) codingModeUI.SetActive(true);
Debug.Log($"⏳ Codingモード開始パズル制限時間: {codingLimitDuration}秒)");
}
public void ApplyBuffsAndResume(string buff1, string buff2)
{
ActivateBuffByName(buff1);
ActivateBuffByName(buff2);
ResumeWorldState(consumeGauge: true);
Debug.Log("🎉 パズル成功!バフを適用して再開。");
}
private void FailCodingModeByTimeout()
{
ResumeWorldState(consumeGauge: true);
Debug.Log("💀 時間切れ! Codingモード失敗バフなし・ゲージ消費。");
}
public void CancelCodingMode()
{
ResumeWorldState(consumeGauge: false);
Debug.Log("↩️ Codingモード手動キャンセル。");
}
private void ResumeWorldState(bool consumeGauge)
{
foreach (var anim in pausedAnimators) { if (anim != null) anim.speed = 1f; }
pausedAnimators.Clear();
foreach (var agent in pausedAgents) { if (agent != null && agent.enabled) agent.isStopped = false; }
pausedAgents.Clear();
EnableAction(moveAction);
EnableAction(turnAction);
isCodingMode = false;
if (codingModeUI != null) codingModeUI.SetActive(false);
if (consumeGauge) currentGauge = 0f;
}
private void ActivateBuffByName(string buffName)
{
switch (buffName)
{
case "AttackUp": attackBuffTimer = buffDuration; break;
case "DefenseUp": defenseBuffTimer = buffDuration; break;
case "Heal": ExecuteHeal(); break;
}
}
private void ExecuteHeal()
{
Debug.Log($"💚 HP回復バフ発動 回復量: {hpHealAmount}");
}
private void UpdateBuffTimers()
{
if (attackBuffTimer > 0f) attackBuffTimer -= Time.deltaTime;
if (defenseBuffTimer > 0f) defenseBuffTimer -= Time.deltaTime;
}
}