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

241 lines
7.7 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;
public class PlayerStatusManager : MonoBehaviour
{
public static PlayerStatusManager Instance { get; private set; }
[Header("デバッグ設定")]
[SerializeField] private bool ignoreGaugeForDebug = true;
[Header("Codingモード用 入力設定")]
[SerializeField] private InputActionProperty zlButtonAction;
[SerializeField] private InputActionProperty zrButtonAction;
[Header("プレイヤー移動・操作制御用 入力設定")]
[SerializeField] private InputActionProperty moveAction;
[SerializeField] private InputActionProperty turnAction;
[Header("パズル制限時間設定")]
[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;
[Header("バフパラメータ設定")]
[Tooltip("攻撃力UP・防御力UPの持続時間 (秒)")]
[SerializeField] private float buffDuration = 10f;
[Tooltip("攻撃力UP時のダメージ倍率")]
[SerializeField] private float attackBuffMultiplier = 1.5f;
[Tooltip("防御力UP時の被ダメージ軽減率")]
[SerializeField] private float defenseBuffMultiplier = 0.5f;
[Tooltip("HP回復バフ発動時の回復量")]
[SerializeField] private float hpHealAmount = 30f;
private float attackBuffTimer = 0f;
private float defenseBuffTimer = 0f;
private bool isCodingMode = false;
public GameObject successEffectPrefab;
// エフェクトを出す位置(合体したブロックの少し上など)
public Transform effectSpawnPoint;
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 isBothHeld = zlVal > 0.5f && zrVal > 0.5f;
bool isAnyTriggered = zlButtonAction.action.triggered || zrButtonAction.action.triggered;
if (isBothHeld && isAnyTriggered)
{
if (!isCodingMode)
{
if (ignoreGaugeForDebug || currentGauge >= maxGauge)
{
StartCodingMode();
}
else
{
Debug.LogWarning($"⚠️ ゲージ不足のためCodingModeを開始できません。現在: {currentGauge} / 必要: {maxGauge}");
}
}
else
{
CancelCodingMode();
}
}
}
private void StartCodingMode()
{
isCodingMode = true;
codingTimer = codingLimitDuration;
// 1. プレイヤーの移動制御をロック
DisableAction(moveAction);
DisableAction(turnAction);
// 2. パズルブロックの状態・位置を全リセット
PuzzleBlock.ResetAllBlocksInScene();
// 3. 敵のアニメーション・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)
{
Instantiate(successEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
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;
}
}