Files
beyond/Assets/Scripts/CameraShake.cs
2024-11-20 15:21:28 +01:00

155 lines
3.9 KiB
C#

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<Camera>();
if (mainCamera == null)
{
Debug.LogError("No camera found. Please assign or tag a camera.");
return;
}
boxCollider = GetComponent<BoxCollider>();
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());
}
}
}