Files
VRProject/Assets/_Scripts/PlayerStatusManager.cs
2026-07-21 16:45:01 +09:00

180 lines
6.1 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; }
[SerializeField] private InputActionProperty zlButtonAction;
[SerializeField] private InputActionProperty zrButtonAction;
[SerializeField] private InputActionProperty moveAction;
[SerializeField] private InputActionProperty turnAction;
[SerializeField] private float codingLimitDuration = 15f;
private float codingTimer = 0f;
[SerializeField] private float maxGauge = 100f;
[SerializeField] private float currentGauge = 0f;
[SerializeField] private GameObject codingModeUI;
[SerializeField] private PuzzleGridBoard puzzleBoard; // 盤面参照
[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 Update()
{
CheckComboInput();
if (!isCodingMode)
{
UpdateBuffTimers();
}
else
{
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;
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)
{
StartCodingMode();
}
else if (isCodingMode)
{
CancelCodingMode(); // 手動キャンセルはゲージ維持
}
}
}
private void StartCodingMode()
{
isCodingMode = true;
codingTimer = codingLimitDuration; // タイマーリセット
if (puzzleBoard != null) puzzleBoard.ClearBoard();
if (moveAction.action != null) moveAction.action.Disable();
if (turnAction.action != null) turnAction.action.Disable();
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();
if (moveAction.action != null) moveAction.action.Enable();
if (turnAction.action != null) turnAction.action.Enable();
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;
}
}