效果
让镜头在指定时间x内,不断在自身原始位置周围选点(半径为y的球形区域内),并将位置设置到该点处。
效果结束后,将镜头设置回原来的位置
做法
在x内,每隔1帧或多帧设置一次位置
-
位置 = 原始位置 + Random.insideUnitSphere * y
image.png
代码
using System;
using System.Collections;
using UnityEngine;
public class CameraShake : MonoBehaviour
{
private Transform _camTrans;
private Transform CamTrans
{
get
{
if (_camTrans == null)
{
_camTrans = Camera.main.transform;
_originalLocalPos = CamTrans.localPosition;
}
return _camTrans;
}
}
private Vector3 _originalLocalPos;
private static CameraShake instance;
public static CameraShake Instance
{
get
{
if (instance == null)
{
GameObject camShake = new GameObject("CameraShake");
instance = camShake.AddComponent<CameraShake>();
var parentGo = GameObject.Find("Singleton");
if (parentGo == null)
{
parentGo = new GameObject("Singleton");
UnityEngine.Object.DontDestroyOnLoad(parentGo);
}
camShake.transform.SetParent(parentGo.transform);
}
return instance;
}
}
private IEnumerator shakeCoroutine;
public void ShakeCamera(CamShakeCfg cfg)
{
ShakeCamera(cfg.Duration, cfg.MaxShakeDistance, cfg.Rate);
}
/// <summary>
/// 相机震动
/// </summary>
/// <param name="duration">震动持续时间</param>
/// <param name="shakeAmount">振幅(震动厉害程度)</param>
/// <param name="decreaseFactor">震动减缓的速率</param>
public void ShakeCamera(float duration = 0.1f, float maxShakeDistance = 0.5f, float rate = 1f)
{
if (!IsEnabled)
{
return;
}
if (shakeCoroutine != null)
shakeCoroutine = null;
shakeCoroutine = ShakeCoroutine(duration, maxShakeDistance, rate);
StartCoroutine(shakeCoroutine);
}
private IEnumerator ShakeCoroutine(float duration, float maxShakeDistance, float rate)
{
float timer = duration;
while (timer > 0f)
{
CamTrans.localPosition = _originalLocalPos + UnityEngine.Random.insideUnitSphere * maxShakeDistance;
timer -= Time.deltaTime * rate;
yield return new WaitForSeconds(Time.deltaTime * rate);
}
CamTrans.localPosition = _originalLocalPos;
if (shakeCoroutine != null)
{
StopCoroutine(shakeCoroutine);
shakeCoroutine = null;
}
}
#region 激活与否
private const string CameraShakeEnabledStorageKey = "CameraShakeEnabled";
private const int EnableSign = 1;
private const int DisableSign = 0;
// 默认激活
public bool IsEnabled { get { return PlayerPrefs.GetInt(CameraShakeEnabledStorageKey, EnableSign) != DisableSign; } }
public void Enable()
{
if (!IsEnabled)
{
PlayerPrefs.SetInt(CameraShakeEnabledStorageKey, EnableSign);
ChangeEnableStateEvent?.Invoke(true);
}
}
public void Disable()
{
if (IsEnabled)
{
PlayerPrefs.SetInt(CameraShakeEnabledStorageKey, DisableSign);
ChangeEnableStateEvent?.Invoke(false);
}
}
public event Action<bool> ChangeEnableStateEvent;
#endregion
}
[System.Serializable]
public class CamShakeCfg
{
[Header("震动持续时间")]
public float Duration = 0.1f;
[Header("振幅(震动厉害程度)")]
public float MaxShakeDistance = 0.5f;
[Header("震动减缓的速率")]
public float Rate = 1f;
}
