155 lines
3.9 KiB
C#
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());
|
|
}
|
|
}
|
|
}
|