235 lines
6.6 KiB
C#
235 lines
6.6 KiB
C#
using UnityEngine;
|
|
|
|
public class GlobalGlitchRuntimeController : MonoBehaviour
|
|
{
|
|
public static GlobalGlitchRuntimeController Instance { get; private set; }
|
|
|
|
[Header("Runtime Glitch Defaults")]
|
|
public float defaultTriggerIntensity = 0.7f;
|
|
public float defaultHoldDuration = 0.05f;
|
|
public float defaultRecoverDuration = 0.16f;
|
|
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)
|
|
TriggerGlitch();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
float delta = useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
|
UpdatePulse(delta);
|
|
UpdateWave(delta);
|
|
}
|
|
|
|
public void TriggerGlitch()
|
|
{
|
|
TriggerGlitch(defaultTriggerIntensity, defaultHoldDuration, defaultRecoverDuration);
|
|
}
|
|
|
|
public void TriggerGlitch(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 GlobalGlitchRuntimeController EnsureInstance()
|
|
{
|
|
if (Instance != null)
|
|
return Instance;
|
|
|
|
GlobalGlitchRuntimeController existing = SceneObjectLookupCache.FindFirst<GlobalGlitchRuntimeController>();
|
|
if (existing != null)
|
|
{
|
|
Instance = existing;
|
|
return existing;
|
|
}
|
|
|
|
GameObject runtimeObject = new GameObject("__global_glitch_runtime");
|
|
Instance = runtimeObject.AddComponent<GlobalGlitchRuntimeController>();
|
|
return Instance;
|
|
}
|
|
|
|
public static void Trigger(float intensity, float holdDuration, float recoverDurationSeconds)
|
|
{
|
|
EnsureInstance().TriggerGlitch(intensity, holdDuration, recoverDurationSeconds);
|
|
}
|
|
|
|
public static void TriggerDefault()
|
|
{
|
|
EnsureInstance().TriggerGlitch();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|