using UnityEngine; namespace Beyond { public class CameraShaker : MonoBehaviour { [Header("Shake Settings")] public float amplitude = 0.1f; // Siła drgania public float duration = 1.0f; // Czas trwania drgania public float frequency = 20f; // Prędkość drgania [Header("Shake Curve")] public AnimationCurve shakeCurve = AnimationCurve.EaseInOut(0, 1, 1, 0); // Krzywa efektu drgania private float shakeTime = 0f; private Vector3 localShakeOffset = Vector3.zero; private Transform mainCamera; private bool isShaking = false; private Vector3 lastShakeOffset = Vector3.zero; void Start() { mainCamera = Camera.main?.transform; // Pobranie MainCamera if (mainCamera == null) { Debug.LogError("CameraShaker: MainCamera not found!"); enabled = false; return; } enabled = true; // Skrypt może być włączony, ale shake działa tylko po evencie } public void StartShake() { if (isShaking) return; // Jeśli shake już działa, nie uruchamiaj ponownie isShaking = true; shakeTime = 0f; lastShakeOffset = Vector3.zero; // Reset poprzedniego przesunięcia } void LateUpdate() { if (isShaking && shakeTime < duration) { shakeTime += Time.deltaTime; float shakeStrength = amplitude * shakeCurve.Evaluate(shakeTime / duration); // Płynne drgania na bazie Perlin Noise float x = (Mathf.PerlinNoise(Time.time * frequency, 0) * 2 - 1) * shakeStrength; float y = (Mathf.PerlinNoise(0, Time.time * frequency) * 2 - 1) * shakeStrength; float z = (Mathf.PerlinNoise(Time.time * frequency, Time.time * frequency) * 2 - 1) * shakeStrength; // Nowe przesunięcie localShakeOffset = new Vector3(x, y, z); // Usuwamy poprzednie przesunięcie, dodajemy nowe mainCamera.localPosition -= lastShakeOffset; mainCamera.localPosition += localShakeOffset; // Zapamiętujemy ostatnie przesunięcie lastShakeOffset = localShakeOffset; } else if (shakeTime >= duration) { isShaking = false; mainCamera.localPosition -= lastShakeOffset; // Resetujemy shake lastShakeOffset = Vector3.zero; } } } }