射击震屏效果——Unity随手记(2021.2.15)

今天实现的内容:

震屏效果逻辑

震屏效果,也就是射击时给予摄像机的旋转一个偏移量,再逐渐复原。我们写了一个弹簧工具来帮助实现上述效果。

这个工具主要是用来将产生偏移后的摄像机逐渐归正。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 摄像机弹簧工具 用于帮助实现摄像机震屏效果
public class CameraSpringUtility
{
    
    
    // 震屏强度参数
    [HideInInspector]
    public Vector3 value;

    // 频率
    private float m_frequence;
    // 阻尼
    private Vector3 m_damp;
    // 阻尼大小
    private float m_dampValue;

    // 构造函数
    public CameraSpringUtility(float _frequence, float _dampValue)
    {
    
    
        m_frequence = _frequence;
        m_dampValue = _dampValue;
    }

    // 运用阻尼 更新value
    public void UpdateSpring(float _deltaTime, Vector3 _target) //_target是指阻尼要恢复到的位置 一般是zero
    {
    
    
        // 运用阻尼
        value -= _deltaTime * m_frequence * m_damp;
        // 计算阻尼
        m_damp = Vector3.Lerp(m_damp, value - _target, m_dampValue * _deltaTime);
    }
}

其中,m_frequence用于振动频率的控制,越大抖的越快,但是好像没什么具体作用,毕竟抖动频率应该只和开火频率有关,m_frequence这样用应该也只是又一个用于调整归正速度的参数。m_dampValue才是我们真正想要用来调整归正速度的参数,其控制插值的t大小。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 相机弹簧 用于实现相机震屏功能
public class CameraSpring : MonoBehaviour
{
    
    
    // Y轴、Z轴的最小反冲范围
    public Vector2 minRecoilRange;
    // Y轴、Z轴的最大反冲范围
    public Vector2 maxRecoilRange;
    // 振动频率
    [Tooltip("振动频率")]
    public float frequence = 25f;
    // 阻尼大小
    [Tooltip("阻尼大小")]
    public float dampValue = 15f;

    // 摄像机弹簧工具
    private CameraSpringUtility springUtility;
    // 缓存摄像机的Transform
    private Transform cameraSpringTransform;

    // 开始震屏
    public void StartCameraSpring()
    {
    
    
        // 将一个随机的震屏强度赋给springUtility.value
        springUtility.value = new Vector3(0,
            Random.Range(minRecoilRange.x, maxRecoilRange.x),
            Random.Range(minRecoilRange.y, maxRecoilRange.y));
    }

    private void Start()
    {
    
    
        springUtility = new CameraSpringUtility(frequence, dampValue);
        cameraSpringTransform = this.transform;
    }

    private void Update()
    {
    
    
        springUtility.UpdateSpring(Time.deltaTime, Vector3.zero);
        cameraSpringTransform.localRotation = Quaternion.Slerp(
            cameraSpringTransform.localRotation,
            Quaternion.Euler(springUtility.value),
            Time.deltaTime * 10f);
    }
}

以上代码将一个随机的旋转偏移量运用到摄像机来达到震屏效果,再调用springUtility.UpdateSpring(Time.deltaTime, Vector3.zero);来归正摄像机。

    // 使用后坐力 交给外部枪械脚本来使用
    public void DoRecoil()
    {
    
    
        m_currentRecoil += recoilRange;
        m_currentRecoilTime = 0; //将开枪时间设置为0
        cameraSpring.StartCameraSpring();
    }

脚本的运用

由于摄像机震屏和后坐力的产生原因都是因为开火,所以在运用后坐力的函数DoRecoil中调用cameraSpring.StartCameraSpring();就可以实现效果。
最后,将CameraSpring脚本挂到一个作为摄像机的节点之下的一个节点,如果你愿意,可以让振动只作用于摄像机,我这里振动依旧会作用到枪上。
在这里插入图片描述


BUG以及缺陷:

暂无


值得注意的:

将这个CameraVibrationHolder放到真正的摄像机的上一级就行了,这样就只会作用到摄像机。
在这里插入图片描述
如果你的项目单独设置了一个GunCamera,也可以将GunCamera也放到Holder下面。
在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/qq_37856544/article/details/113815577