using System.Collections.Generic;
using UnityEngine;
namespace CameraShake
{
///
/// Camera shaker component registeres new shakes, holds a list of active shakes, and applies them to the camera additively.
///
public class CameraShaker : MonoBehaviour
{
public static CameraShaker Instance;
public static CameraShakePresets Presets;
readonly List activeShakes = new List();
[Tooltip("Transform which will be affected by the shakes.\n\nCameraShaker will set this transform's local position and rotation.")]
[SerializeField]
Transform cameraTransform;
[Tooltip("Scales the strength of all shakes.")]
[Range(0, 1)]
[SerializeField]
public float StrengthMultiplier = 1;
public CameraShakePresets ShakePresets;
///
/// Adds a shake to the list of active shakes.
///
public static void Shake(ICameraShake shake)
{
if (IsInstanceNull()) return;
Instance.RegisterShake(shake);
}
///
/// Adds a shake to the list of active shakes.
///
public void RegisterShake(ICameraShake shake)
{
shake.Initialize(cameraTransform.position,
cameraTransform.rotation);
activeShakes.Add(shake);
}
///
/// Sets the transform which will be affected by the shakes.
///
public void SetCameraTransform(Transform cameraTransform)
{
cameraTransform.localPosition = Vector3.zero;
cameraTransform.localEulerAngles = Vector3.zero;
this.cameraTransform = cameraTransform;
}
private void Awake()
{
Instance = this;
ShakePresets = new CameraShakePresets(this);
Presets = ShakePresets;
if (cameraTransform == null)
cameraTransform = transform;
}
public void UpdateShake()
{
if (cameraTransform == null) return;
Displacement cameraDisplacement = Displacement.Zero;
for (int i = activeShakes.Count - 1; i >= 0; i--)
{
if (activeShakes[i].IsFinished)
{
activeShakes.RemoveAt(i);
}
else
{
activeShakes[i].Update(Time.deltaTime, cameraTransform.position, cameraTransform.rotation);
cameraDisplacement += activeShakes[i].CurrentDisplacement;
}
}
cameraTransform.localPosition = transform.localPosition + StrengthMultiplier * cameraDisplacement.position;
cameraTransform.localRotation *= Quaternion.Euler(StrengthMultiplier * cameraDisplacement.eulerAngles);
}
private static bool IsInstanceNull()
{
if (Instance == null)
{
Debug.LogError("CameraShaker Instance is missing!");
return true;
}
return false;
}
}
}