using SmoothShakeFree; using System.Collections; using UnityEngine; using UnityEngine.UI; public class globalNoteEffect : MonoBehaviour { public static globalNoteEffect Instance { get; private set; } [Header("Camera Shake Event")] public float cameraShakeAmplitude = 0.12f; [Header("Flash Blink Event")] public Image flashBlinkImage; public float flashBlinkFadeDuration = 0.2f; [Header("Camera Dash Event")] public float targetCameraZPosition = -6.5f; public AnimationCurve cameraDashCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); public float cameraDashDuration = 0.12f; [Header("Camera Wave FX")] public float cameraWaveEnterDuration = 0.12f; public float cameraWaveRecoverDuration = 0.12f; [Header("Camera Glitch FX")] public float cameraGlitchEnterDuration = 0.08f; public float cameraGlitchRecoverDuration = 0.12f; [Header("Camera Monochrome FX")] public float cameraMonochromeEnterDuration = 0.1f; public float cameraMonochromeRecoverDuration = 0.14f; [Header("Screenshot Scale FX")] public float screenshotScaleStartOpacity = 0.5f; public float screenshotScaleFadeDuration = 0.22f; public float screenshotScaleEndScale = 1.12f; private Transform cachedCameraTransform; private Coroutine flashBlinkCoroutine; private Coroutine cameraDashCoroutine; private float cameraBaseLocalZ; private bool hasCameraBaseLocalZ; private void Awake() { if (Instance == null) { Instance = this; } else if (Instance != this) { Destroy(gameObject); return; } CacheCameraTransform(); PrewarmRuntime(); } private void Start() { SetFlashImageAlpha(0f); } private void OnEnable() { CacheCameraTransform(); SetFlashImageAlpha(0f); PrewarmRuntime(); } private void LateUpdate() { if (cachedCameraTransform == null) { CacheCameraTransform(); } if (cachedCameraTransform != null && cameraDashCoroutine == null) { cameraBaseLocalZ = cachedCameraTransform.localPosition.z; hasCameraBaseLocalZ = true; } } private void CacheCameraTransform() { if (Camera.main != null) { cachedCameraTransform = Camera.main.transform; cameraBaseLocalZ = cachedCameraTransform.localPosition.z; hasCameraBaseLocalZ = true; } } public void PrewarmRuntime() { CacheCameraTransform(); if (cachedCameraTransform != null) { SmoothShake shake = cachedCameraTransform.GetComponent(); if (shake == null) { shake = cachedCameraTransform.gameObject.AddComponent(); } if (shake.positionShake == null) shake.positionShake = new Shaker(); if (shake.rotationShake == null) shake.rotationShake = new Shaker(); if (shake.shakers == null || shake.shakers.Length != 2) shake.shakers = new[] { shake.positionShake, shake.rotationShake }; if (shake.sum == null || shake.sum.Length != 2) shake.sum = new Vector3[2]; } GlobalDistortionRuntimeController.EnsureInstance(); GlobalGlitchRuntimeController.EnsureInstance(); GlobalMonochromeRuntimeController.EnsureInstance(); GlobalAfterimageRuntimeController.EnsureInstance(); } public static void TryTrigger(string noteFunction) { if (string.IsNullOrWhiteSpace(noteFunction)) return; globalNoteEffect controller = GetOrCreateInstance(); if (controller == null) return; controller.TriggerInternal(noteFunction.Trim()); } private static globalNoteEffect GetOrCreateInstance() { if (Instance != null) return Instance; globalNoteEffect found = SceneObjectLookupCache.FindAny(); if (found != null) { Instance = found; return found; } GameObject runtimeObject = new GameObject("__global_note_effect_runtime"); return runtimeObject.AddComponent(); } private void TriggerInternal(string noteFunction) { switch (noteFunction) { case "CameraShakeEvent": TriggerCameraShake(); break; case "FlashBlinkEvent": TriggerFlashBlink(); break; case "CameraScaleEvent": TriggerCameraDash(); break; case "CameraWaveFX": TriggerCameraWaveFx(); break; case "CameraGlitchFX": TriggerCameraGlitchFx(); break; case "CameraMonochromeFX": TriggerCameraMonochromeFx(); break; case "ScreenshotScale": TriggerScreenshotScaleFx(); break; } } private void TriggerCameraShake() { CacheCameraTransform(); if (cachedCameraTransform == null) return; float amplitudeValue = Mathf.Max(0f, cameraShakeAmplitude); if (amplitudeValue <= 0f) return; SmoothShake shake = cachedCameraTransform.GetComponent(); if (shake == null) { shake = cachedCameraTransform.gameObject.AddComponent(); } if (shake.positionShake == null) shake.positionShake = new Shaker(); if (shake.rotationShake == null) shake.rotationShake = new Shaker(); shake.positionShake.noiseType = Shaker.NoiseType.SineWave; shake.positionShake.amplitude = new Vector3(amplitudeValue, amplitudeValue, 0f); shake.positionShake.frequency = new Vector3(18f, 18f, 0f); shake.rotationShake.amplitude = Vector3.zero; shake.rotationShake.frequency = Vector3.zero; shake.timeSettings.constantShake = false; shake.timeSettings.fadeInDuration = 0.02f; shake.timeSettings.holdDuration = 0.04f; shake.timeSettings.fadeOutDuration = 0.05f; if (shake.timeSettings.fadeInCurve == null || shake.timeSettings.fadeInCurve.length == 0) shake.timeSettings.fadeInCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); if (shake.timeSettings.fadeOutCurve == null || shake.timeSettings.fadeOutCurve.length == 0) shake.timeSettings.fadeOutCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); shake.shakers = new[] { shake.positionShake, shake.rotationShake }; shake.sum = new Vector3[2]; shake.StartShake(); } private void TriggerFlashBlink() { if (flashBlinkImage == null) return; if (flashBlinkCoroutine != null) { StopCoroutine(flashBlinkCoroutine); } flashBlinkCoroutine = StartCoroutine(FlashBlinkCoroutine()); } private IEnumerator FlashBlinkCoroutine() { SetFlashImageAlpha(1f); float duration = Mathf.Max(0.01f, flashBlinkFadeDuration); float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); SetFlashImageAlpha(1f - t); yield return null; } SetFlashImageAlpha(0f); flashBlinkCoroutine = null; } private void TriggerCameraDash() { CacheCameraTransform(); if (cachedCameraTransform == null) return; if (cameraDashCoroutine != null) { StopCoroutine(cameraDashCoroutine); if (hasCameraBaseLocalZ) { Vector3 resetPosition = cachedCameraTransform.localPosition; resetPosition.z = cameraBaseLocalZ; cachedCameraTransform.localPosition = resetPosition; } } cameraDashCoroutine = StartCoroutine(CameraDashCoroutine()); } private IEnumerator CameraDashCoroutine() { if (!hasCameraBaseLocalZ) { cameraBaseLocalZ = cachedCameraTransform.localPosition.z; hasCameraBaseLocalZ = true; } float baseLocalZ = cameraBaseLocalZ; float targetZ = targetCameraZPosition; if (Mathf.Approximately(targetZ, baseLocalZ)) { targetZ = baseLocalZ + 1.5f; } float duration = Mathf.Max(0.01f, cameraDashDuration); AnimationCurve curve = cameraDashCurve == null || cameraDashCurve.length == 0 ? AnimationCurve.EaseInOut(0f, 0f, 1f, 1f) : cameraDashCurve; float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); float curvedT = curve.Evaluate(t); Vector3 position = cachedCameraTransform.localPosition; position.z = Mathf.LerpUnclamped(baseLocalZ, targetZ, curvedT); cachedCameraTransform.localPosition = position; yield return null; } elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); float curvedT = curve.Evaluate(t); Vector3 position = cachedCameraTransform.localPosition; position.z = Mathf.LerpUnclamped(targetZ, baseLocalZ, curvedT); cachedCameraTransform.localPosition = position; yield return null; } Vector3 finalPosition = cachedCameraTransform.localPosition; finalPosition.z = baseLocalZ; cachedCameraTransform.localPosition = finalPosition; cameraDashCoroutine = null; } private void TriggerCameraWaveFx() { GlobalDistortionRuntimeController.TriggerWaveEffect( Mathf.Max(0.0001f, cameraWaveEnterDuration), Mathf.Max(0.0001f, cameraWaveRecoverDuration) ); } private void TriggerCameraGlitchFx() { GlobalGlitchRuntimeController.TriggerWaveEffect( Mathf.Max(0.0001f, cameraGlitchEnterDuration), Mathf.Max(0.0001f, cameraGlitchRecoverDuration) ); } private void TriggerCameraMonochromeFx() { GlobalMonochromeRuntimeController.Trigger( Mathf.Max(0.0001f, cameraMonochromeEnterDuration), Mathf.Max(0.0001f, cameraMonochromeRecoverDuration) ); } private void TriggerScreenshotScaleFx() { GlobalAfterimageRuntimeController.Trigger( Mathf.Clamp01(screenshotScaleStartOpacity), Mathf.Max(0.0001f, screenshotScaleFadeDuration), Mathf.Max(1f, screenshotScaleEndScale) ); } private void SetFlashImageAlpha(float alpha) { if (flashBlinkImage == null) return; Color color = flashBlinkImage.color; color.a = Mathf.Clamp01(alpha); flashBlinkImage.color = color; } }