
通过缩放Camera的Field of View实现相机拉近/远效果,比如按下摇杆视野拉近,松开摇杆视野拉远
利用AnimationCurve控制相机抖动曲线,实现类似爆炸效果视野震动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraEffectTest : MonoBehaviour
{
[Space]
//震动时间
[SerializeField] float shakeDuration = 0.5f;
//震动强度
[SerializeField] float shakeStrength = 1;
//震动曲线
[SerializeField] AnimationCurve shakeCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.13f, 0.4f), new Keyframe(0.28f, -0.33f), new Keyframe(0.45f, 0.4f), new Keyframe(0.63f, -0.3f), new Keyframe(0.84f, 0.35f), new Keyframe(1, 0));
//----------
[Space]
//视野缩放速度
[SerializeField, Range(0.01f, 1)] float scaleFieldLerpSpeed = 0.1f;
//----------
//相机
public Camera mainCamera { get; private set; }
//震动节点
private Transform shakeNode;
//----------
private void Awake()
{
mainCamera = Camera.main;
if (mainCamera == null)
mainCamera = GetComponentInChildren<Camera>();
shakeNode = transform.Find("ShakeNode");
if (shakeNode == null)
shakeNode = transform;
}
private void Start()
{
InitField();
InitShake();
}
private void Update()
{
UpdateShake();
if (Input.GetMouseButtonDown(1))
StartShakeWithDirection(Vector3.one);
if (Input.GetMouseButtonDown(0))
ScaleFieldOfView(10);
if (Input.GetMouseButtonUp(0))
ResetFieldOfView();
}
private void LateUpdate()
{
UpdateField();
}
#region --- Screen Shake ---
//节点初始位置
private Vector3 shakeNodeInitPos = Vector3.zero;
private float shakeTime = 0;
private bool shakeRandom = false;
private bool isShaking = false;
private Vector3 shakeDirection;
private void InitShake()
{
shakeNodeInitPos = shakeNode.transform.position;
shakeTime = 0;
isShaking = false;
shakeDirection = Vector3.zero;
}
//开始震动
public void StartShakeWithDirection(Vector3 direction)
{
//停止未完成的震动
if (isShaking)
StopShake();
shakeTime = 0;
shakeDirection = direction.normalized;
isShaking = true;
shakeRandom = false;
}
public void StartShakeRandomDirection()
{
if (isShaking)
StopShake();
shakeTime = 0;
shakeDirection = (new Vector3(Random.Range(0.0f, 1.0f), 0, Random.Range(0.0f, 1.0f))).normalized;
isShaking = true;
shakeRandom = false;
}
public void StartShakeRandomDirAndPower()
{
if (isShaking)
StopShake();
shakeTime = 0;
isShaking = true;
shakeRandom = true;
}
// ----------
private void UpdateShake()
{
if (isShaking)
{
shakeTime += Time.deltaTime;
if (shakeTime < shakeDuration)
{
if (shakeRandom)
shakeNode.transform.localPosition = shakeNodeInitPos + Random.insideUnitSphere * shakeStrength;
else
shakeNode.transform.localPosition = shakeNodeInitPos + shakeDirection * shakeStrength * shakeCurve.Evaluate((shakeTime % 1) / shakeDuration);
}
else
StopShake();
}
}
//停止震动
private void StopShake()
{
if (shakeNode != null)
shakeNode.localPosition = shakeNodeInitPos;
shakeDirection = Vector3.zero;
isShaking = false;
shakeTime = 0;
}
#endregion
#region --- Scale FieldOfView ---
//默认视野值
private float defaultFieldValue;
private bool isScaleField;
private float targetFieldValue;
private void InitField()
{
defaultFieldValue = mainCamera.fieldOfView;
isScaleField = false;
targetFieldValue = defaultFieldValue;
}
private void UpdateField()
{
if (isScaleField)
{
if (Mathf.Abs(mainCamera.fieldOfView - targetFieldValue) > 0.01f)
{
mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOfView, targetFieldValue, scaleFieldLerpSpeed);
}
else
{
StopField();
}
}
}
private void StopField()
{
isScaleField = false;
targetFieldValue = defaultFieldValue;
}
public void ScaleFieldOfView(float changeValue)
{
targetFieldValue = defaultFieldValue + changeValue;
isScaleField = true;
}
public void ResetFieldOfView()
{
ScaleFieldOfView(0);
}
#endregion
}
本文来自博客园,作者:萧然CS,转载请注明原文链接:https://www.cnblogs.com/z-c-s/p/15112871.html
浙公网安备 33010602011771号