106 lines
3.4 KiB
C#
106 lines
3.4 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.XR.Interaction.Toolkit.Locomotion.Movement;
|
|
|
|
namespace VRShopping.Player
|
|
{
|
|
// 플레이어 허기 게이지. 시간이 지나면 깎이고 0이 되면 이동 속도가 느려진다.
|
|
// Complete XR Origin Set Up 루트에 부착 (PlayerWallet과 동일 위치).
|
|
public class PlayerHunger : MonoBehaviour
|
|
{
|
|
public static PlayerHunger Instance { get; private set; }
|
|
|
|
[Header("Gauge")]
|
|
[SerializeField, Min(0f)] private float _maxHunger = 100f;
|
|
[SerializeField, Min(0f)] private float _initialHunger = 80f;
|
|
[SerializeField, Min(0f)] private float _decayPerSecond = 1.5f;
|
|
|
|
[Header("Slow Penalty")]
|
|
// 굶주린 상태에서의 이동 속도 (원래 속도와 곱해지지 않고 절댓값으로 대체)
|
|
[SerializeField, Min(0f)] private float _starvedMoveSpeed = 0.6f;
|
|
// ContinuousMoveProvider의 서브클래스(예: Starter Assets의 DynamicMoveProvider)도 그대로 할당 가능
|
|
[SerializeField] private ContinuousMoveProvider _moveProvider;
|
|
|
|
// 0~_maxHunger 사이의 현재 값 (UI 갱신용 이벤트로 통지)
|
|
public event Action<float, float> OnHungerChanged; // (current, max)
|
|
|
|
public float Current { get; private set; }
|
|
public float Max => _maxHunger;
|
|
public bool IsStarved => Current <= 0f;
|
|
|
|
private float _originalMoveSpeed;
|
|
private bool _slowApplied;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this) { Destroy(this); return; }
|
|
Instance = this;
|
|
|
|
Current = Mathf.Clamp(_initialHunger, 0f, _maxHunger);
|
|
|
|
// MoveProvider 원본 속도 캐싱
|
|
if (_moveProvider != null) _originalMoveSpeed = _moveProvider.moveSpeed;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (Instance == this) Instance = null;
|
|
// 씬 종료 시 변경한 속도 복구
|
|
RestoreMoveSpeed();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
OnHungerChanged?.Invoke(Current, _maxHunger);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (Current > 0f)
|
|
{
|
|
Current = Mathf.Max(0f, Current - _decayPerSecond * Time.deltaTime);
|
|
OnHungerChanged?.Invoke(Current, _maxHunger);
|
|
}
|
|
|
|
UpdateSlowState();
|
|
}
|
|
|
|
// 시식 등으로 허기를 회복
|
|
public void Eat(float amount)
|
|
{
|
|
if (amount <= 0f) return;
|
|
|
|
Current = Mathf.Min(_maxHunger, Current + amount);
|
|
OnHungerChanged?.Invoke(Current, _maxHunger);
|
|
|
|
UpdateSlowState();
|
|
}
|
|
|
|
private void UpdateSlowState()
|
|
{
|
|
if (_moveProvider == null) return;
|
|
|
|
bool shouldSlow = IsStarved;
|
|
if (shouldSlow && !_slowApplied)
|
|
{
|
|
_moveProvider.moveSpeed = _starvedMoveSpeed;
|
|
_slowApplied = true;
|
|
}
|
|
else if (!shouldSlow && _slowApplied)
|
|
{
|
|
_moveProvider.moveSpeed = _originalMoveSpeed;
|
|
_slowApplied = false;
|
|
}
|
|
}
|
|
|
|
private void RestoreMoveSpeed()
|
|
{
|
|
if (_moveProvider != null && _slowApplied)
|
|
{
|
|
_moveProvider.moveSpeed = _originalMoveSpeed;
|
|
_slowApplied = false;
|
|
}
|
|
}
|
|
}
|
|
}
|