Files
bansonic_beta_main/Assets/scripts/rendering/GlobalDistortionRuntimeController.cs
2026-07-24 04:43:13 +08:00

244 lines
6.9 KiB
C#

using UnityEngine;
public class GlobalDistortionRuntimeController : MonoBehaviour
{
public static GlobalDistortionRuntimeController Instance { get; private set; }
[Header("Runtime Distortion Defaults")]
public float defaultTriggerIntensity = 0.45f;
public float defaultHoldDuration = 0.06f;
public float defaultRecoverDuration = 0.18f;
public AnimationCurve recoveryCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f);
public bool useUnscaledTime = true;
public bool triggerOnEnable = false;
private static float sPersistentIntensity;
private static float sPulseIntensity;
private static float sWaveIntensity;
private float activePulseIntensity;
private float holdRemaining;
private float recoverElapsed;
private float recoverDuration;
private bool recovering;
private float waveTargetIntensity;
private float waveEnterDuration;
private float waveRecoverDuration;
private float waveElapsed;
private WavePhase wavePhase = WavePhase.None;
public static float RuntimeIntensity => Mathf.Clamp01(sPersistentIntensity + sPulseIntensity + sWaveIntensity);
private enum WavePhase
{
None,
Enter,
Exit
}
private void Awake()
{
if (Instance == null)
{
Instance = this;
return;
}
if (Instance != this)
{
Destroy(gameObject);
}
}
private void OnEnable()
{
if (triggerOnEnable)
{
TriggerDistortion();
}
}
private void Update()
{
float delta = useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
UpdatePulse(delta);
UpdateWave(delta);
}
public void TriggerDistortion()
{
TriggerDistortion(defaultTriggerIntensity, defaultHoldDuration, defaultRecoverDuration);
}
public void TriggerDistortion(float intensity, float holdDuration, float recoveryDurationSeconds)
{
intensity = Mathf.Clamp01(intensity);
holdDuration = Mathf.Max(0f, holdDuration);
recoveryDurationSeconds = Mathf.Max(0f, recoveryDurationSeconds);
activePulseIntensity = intensity;
holdRemaining = holdDuration;
recoverDuration = recoveryDurationSeconds;
recoverElapsed = 0f;
recovering = recoveryDurationSeconds <= 0f && holdDuration <= 0f;
sPulseIntensity = intensity;
if (holdDuration <= 0f && recoveryDurationSeconds <= 0f)
{
activePulseIntensity = 0f;
sPulseIntensity = 0f;
recovering = false;
}
}
public void SetPersistentIntensity(float intensity)
{
sPersistentIntensity = Mathf.Clamp01(intensity);
}
public void ClearPersistentIntensity()
{
sPersistentIntensity = 0f;
}
public void TriggerWave(float targetIntensity, float enterDurationSeconds, float recoverDurationSeconds)
{
waveTargetIntensity = Mathf.Clamp01(targetIntensity);
waveEnterDuration = Mathf.Max(0.0001f, enterDurationSeconds);
waveRecoverDuration = Mathf.Max(0.0001f, recoverDurationSeconds);
waveElapsed = 0f;
wavePhase = WavePhase.Enter;
sWaveIntensity = 0f;
}
private void UpdatePulse(float delta)
{
if (activePulseIntensity <= 0f && !recovering)
{
sPulseIntensity = 0f;
return;
}
if (holdRemaining > 0f)
{
holdRemaining -= delta;
sPulseIntensity = activePulseIntensity;
if (holdRemaining > 0f)
return;
recovering = recoverDuration > 0f;
recoverElapsed = 0f;
if (!recovering)
{
activePulseIntensity = 0f;
sPulseIntensity = 0f;
return;
}
}
if (!recovering)
{
activePulseIntensity = 0f;
sPulseIntensity = 0f;
return;
}
recoverElapsed += delta;
float normalized = recoverDuration <= 0f ? 1f : Mathf.Clamp01(recoverElapsed / recoverDuration);
float curveValue = recoveryCurve != null && recoveryCurve.length > 0
? recoveryCurve.Evaluate(normalized)
: 1f - normalized;
sPulseIntensity = Mathf.Clamp01(activePulseIntensity * Mathf.Max(0f, curveValue));
if (normalized < 1f)
return;
recovering = false;
activePulseIntensity = 0f;
sPulseIntensity = 0f;
}
private void UpdateWave(float delta)
{
if (wavePhase == WavePhase.None)
{
sWaveIntensity = 0f;
return;
}
waveElapsed += delta;
if (wavePhase == WavePhase.Enter)
{
float normalized = Mathf.Clamp01(waveElapsed / waveEnterDuration);
sWaveIntensity = Mathf.LerpUnclamped(0f, waveTargetIntensity, normalized);
if (normalized < 1f)
return;
sWaveIntensity = waveTargetIntensity;
wavePhase = WavePhase.Exit;
waveElapsed = 0f;
return;
}
float exitNormalized = Mathf.Clamp01(waveElapsed / waveRecoverDuration);
sWaveIntensity = Mathf.LerpUnclamped(waveTargetIntensity, 0f, exitNormalized);
if (exitNormalized < 1f)
return;
sWaveIntensity = 0f;
wavePhase = WavePhase.None;
}
public static GlobalDistortionRuntimeController EnsureInstance()
{
if (Instance != null)
return Instance;
GlobalDistortionRuntimeController existing = SceneObjectLookupCache.FindFirst<GlobalDistortionRuntimeController>();
if (existing != null)
{
Instance = existing;
return existing;
}
GameObject runtimeObject = new GameObject("__global_distortion_runtime");
Instance = runtimeObject.AddComponent<GlobalDistortionRuntimeController>();
return Instance;
}
public static void Trigger(float intensity, float holdDuration, float recoverDurationSeconds)
{
EnsureInstance().TriggerDistortion(intensity, holdDuration, recoverDurationSeconds);
}
public static void TriggerDefault()
{
EnsureInstance().TriggerDistortion();
}
public static void SetPersistent(float intensity)
{
EnsureInstance().SetPersistentIntensity(intensity);
}
public static void ClearPersistent()
{
if (Instance != null)
Instance.ClearPersistentIntensity();
else
sPersistentIntensity = 0f;
}
public static void TriggerWaveEffect(float enterDurationSeconds, float recoverDurationSeconds)
{
EnsureInstance().TriggerWave(1f, enterDurationSeconds, recoverDurationSeconds);
}
public static void TriggerWaveEffect(float intensity, float enterDurationSeconds, float recoverDurationSeconds)
{
EnsureInstance().TriggerWave(intensity, enterDurationSeconds, recoverDurationSeconds);
}
}