chore: Project Restructuring & Theatre
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.Features.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the player's stress level and forwards it to <see cref="Unheimlich.World.CameraSystem.LostFootageRig"/>.
|
||||
/// Stress rises instantly to the requested target and decays back to zero over time when not sustained.
|
||||
///
|
||||
/// Intended to sit on <c>OctoPlayerFP</c> alongside other player-level components.
|
||||
/// Call <see cref="AddStress"/>, <see cref="SetStress"/>, or <see cref="CalmDown"/> from
|
||||
/// gameplay systems (proximity triggers, jump-scares, scripted events, etc.).
|
||||
/// </summary>
|
||||
public class StressController : MonoBehaviour
|
||||
{
|
||||
// ── Inspector ─────────────────────────────────────────────────────────────
|
||||
|
||||
[Header("References")]
|
||||
[Tooltip("The LostFootageRig component on CameraPivot.")]
|
||||
[SerializeField] private Unheimlich.World.CameraSystem.LostFootageRig _rig;
|
||||
|
||||
[Header("Decay")]
|
||||
[Tooltip("Rate at which stress falls back to zero per second when not sustained.")]
|
||||
[SerializeField] private float _decaySpeed = 0.3f;
|
||||
|
||||
[Tooltip("Stress must stay below this threshold for the rig to auto-deactivate.")]
|
||||
[SerializeField] private float _deactivateThreshold = 0.05f;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool _debugSustainStress;
|
||||
[SerializeField] [Range(0f, 1f)] private float _debugStressValue;
|
||||
|
||||
// ── Runtime state ─────────────────────────────────────────────────────────
|
||||
|
||||
private float _currentStress;
|
||||
private float _targetStress;
|
||||
private bool _sustained; // true while an external system holds a target this frame
|
||||
|
||||
// ── Unity lifecycle ───────────────────────────────────────────────────────
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_debugSustainStress)
|
||||
SetStress(_debugStressValue);
|
||||
|
||||
_sustained = false;
|
||||
|
||||
if (_currentStress > _targetStress)
|
||||
_currentStress = Mathf.MoveTowards(_currentStress, _targetStress, _decaySpeed * Time.deltaTime);
|
||||
else
|
||||
_currentStress = _targetStress;
|
||||
|
||||
_targetStress = 0f; // reset each frame; callers must re-assert every Update if sustained
|
||||
|
||||
if (_rig == null)
|
||||
return;
|
||||
|
||||
_rig.StressLevel = _currentStress;
|
||||
|
||||
// Auto-toggle the rig based on stress level.
|
||||
if (!_rig.IsActive && _currentStress > _deactivateThreshold)
|
||||
_rig.SetActive(true);
|
||||
else if (_rig.IsActive && _currentStress <= _deactivateThreshold)
|
||||
_rig.SetActive(false);
|
||||
}
|
||||
|
||||
// ── Public API ────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Sets a one-shot stress spike that will decay naturally next frame.
|
||||
/// For sustained stress, call this every frame from a trigger zone or event.
|
||||
/// </summary>
|
||||
public void SetStress(float value)
|
||||
{
|
||||
_targetStress = Mathf.Max(_targetStress, Mathf.Clamp01(value));
|
||||
_currentStress = Mathf.Max(_currentStress, _targetStress);
|
||||
}
|
||||
|
||||
/// <summary>Adds <paramref name="delta"/> on top of the current target stress.</summary>
|
||||
public void AddStress(float delta) => SetStress(_targetStress + delta);
|
||||
|
||||
/// <summary>Immediately zeroes stress and deactivates the rig.</summary>
|
||||
public void CalmDown()
|
||||
{
|
||||
_currentStress = 0f;
|
||||
_targetStress = 0f;
|
||||
_rig?.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directly activates or deactivates the rig regardless of stress level.
|
||||
/// Useful for scripted sequences where you want the effect without the stress system.
|
||||
/// </summary>
|
||||
public void ForceRig(bool active) => _rig?.SetActive(active);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user