效果
讓鏡頭在指定時(shí)間x內(nèi),不斷在自身原始位置周?chē)x點(diǎn)(半徑為y的球形區(qū)域內(nèi)),并將位置設(shè)置到該點(diǎn)處。
效果結(jié)束后,將鏡頭設(shè)置回原來(lái)的位置
做法
在x內(nèi),每隔1幀或多幀設(shè)置一次位置
-
位置 = 原始位置 + 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>
/// 相機(jī)震動(dòng)
/// </summary>
/// <param name="duration">震動(dòng)持續(xù)時(shí)間</param>
/// <param name="shakeAmount">振幅(震動(dòng)厲害程度)</param>
/// <param name="decreaseFactor">震動(dòng)減緩的速率</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;
// 默認(rèn)激活
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("震動(dòng)持續(xù)時(shí)間")]
public float Duration = 0.1f;
[Header("振幅(震動(dòng)厲害程度)")]
public float MaxShakeDistance = 0.5f;
[Header("震動(dòng)減緩的速率")]
public float Rate = 1f;
}
