using System.Collections; using UnityEngine; using UnityEngine.Events; [RequireComponent(typeof(BoxCollider))] public class CameraShake : MonoBehaviour { [Header("Camera Settings")] public bool useMainCamera = true; public bool useTaggedCamera = false; public string taggedCameraName = "YourTaggedCameraTag"; public bool playOnce = false; [Header("Shake Settings")] public AnimationCurve intensityCurve = AnimationCurve.Linear(0, 1, 1, 1); public float durationSpeed = 1.0f; public float duration = 1.0f; [Header("Audio Settings")] public AudioClip shakeAudioClip; [Header("Events")] public UnityEvent onShakeStart; public UnityEvent onShakeEnd; public UnityEvent onEnter; public UnityEvent onExit; public float endShakeDelay = 0.0f; private Camera mainCamera; private bool isShaking = false; private BoxCollider boxCollider; private bool hasTriggered = false; [Header("Collision Settings")] public float delay = 0f; public bool useTagFilter = false; public string targetTag; public bool triggerOnlyOnce = false; private void Start() { if (useMainCamera) mainCamera = Camera.main; else if (useTaggedCamera) mainCamera = GameObject.FindGameObjectWithTag(taggedCameraName)?.GetComponent(); if (mainCamera == null) { Debug.LogError("No camera found. Please assign or tag a camera."); return; } boxCollider = GetComponent(); if (boxCollider == null) { Debug.LogError("No BoxCollider found. Please attach a BoxCollider component to the GameObject."); return; } } private void OnTriggerEnter(Collider other) { if (triggerOnlyOnce && hasTriggered) return; if (useTagFilter && !other.CompareTag(targetTag)) { Debug.Log("Collision with object with different tag."); return; } hasTriggered = true; if (other.CompareTag("Player")) { onEnter.Invoke(); if (!isShaking) { onShakeStart.Invoke(); StartCoroutine(ShakeCamera()); } } StartCoroutine(InvokeEventWithDelay()); } private void OnTriggerExit(Collider other) { if (other.CompareTag("Player")) { onExit.Invoke(); } } private IEnumerator InvokeEventWithDelay() { yield return new WaitForSeconds(delay); if (onShakeStart != null) { Debug.Log("Event is being invoked."); onShakeStart.Invoke(); } else { Debug.LogWarning("OnShakeStart is not assigned."); } } private IEnumerator ShakeCamera() { isShaking = true; if (shakeAudioClip != null) AudioSource.PlayClipAtPoint(shakeAudioClip, mainCamera.transform.position); float startTime = Time.time; do { float elapsed = Time.time - startTime; float progress = Mathf.Clamp01(elapsed / duration); float intensity = intensityCurve.Evaluate(progress); Vector3 offset = Random.insideUnitSphere * intensity; mainCamera.transform.localPosition = offset; yield return null; } while (Time.time - startTime < duration); yield return new WaitForSeconds(endShakeDelay); isShaking = false; mainCamera.transform.localPosition = Vector3.zero; onShakeEnd.Invoke(); if (playOnce) Destroy(this); } // Public method to start camera shake from other scripts public void StartCameraShake() { if (!isShaking) { onShakeStart.Invoke(); StartCoroutine(ShakeCamera()); } } }