【Unity小技巧】可靠的相机抖动及如何同时处理多个震动

文章目录

每篇一句

围在城里的人想逃出来,站在城外的人想冲进去,婚姻也罢,事业也罢,人生的欲望大都如此。------钱钟书《围城》

前言

相机的抖动我相信大家都不陌生,网上其实已经有非常非常多的教程了,之前我也写过一篇文章,感兴趣的可以先去看看
unity实现简单的摄像机震动效果(包括普通摄像机和虚拟摄像机)

但有时我们可能需要两个震动同时发生,例如,如果我们开启了大门并且又收到伤害,我们希望两个震动结合在一起

我在这里的规则是,更强的震动被优先考虑,但我们不要停止弱震动的进展,而是一起工作,

一旦完成了强震动,弱震动就会继续

最终效果

安装虚拟相机

实现相机抖动的最简单方法是使用cinemachine虚拟相机

导入cinemachine插件

搜索Cinemachine,安装并导入

新建虚拟相机

虚拟相机震动测试

这里body和Aim都不需要,就选择Do nothing

选择Noise ,选择 Basic Multi Channel Perlin

Noise Profile 选择自己喜欢的震动模式(可以挨个自己测试),这里我选择6D Wobble

AmplitudeGain:

FrequencyGain:表示震动的频率

代码控制震动

新增代码控制

csharp 复制代码
using System.Collections.Generic;
using System.Linq;
using Cinemachine;
using UnityEngine;

public class CameraShaker : MonoBehaviour
{
    private readonly List<ShakeRequest> _requests = new List<ShakeRequest>(); // 用于存储震动请求的列表

    private CinemachineBasicMultiChannelPerlin _noise; // CinemachineBasicMultiChannelPerlin组件,用于控制相机震动效果

    private void Awake()
    {
         // 获取CinemachineBasicMultiChannelPerlin组件
        _noise = GetComponent<CinemachineVirtualCamera>()
            .GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    }

    private void Update()
    {
        if (_requests.Count == 0)
        {
            _noise.m_AmplitudeGain = 0; // 如果没有震动请求,将AmplitudeGain设置为0,停止震动效果
            return;
        }
        var strongestShake =_requests.Max(shake => shake.ShakeAmount); // 获取最强烈的震动请求
        _noise.m_AmplitudeGain = strongestShake; // 将AmplitudeGain设置为最强烈的震动请求的幅度
    }

    // 请求相机震动,使用默认的持续时间0
    public void RequestShake(float amount)
    {
       RequestShake(amount, 0);
    }

    // 请求相机震动,指定震动的幅度和持续时间
    public void RequestShake(float amount, float time)
    {
        _requests.Add(new ShakeRequest // 向列表中添加一个新的ShakeRequest
        {
            ShakeAmount = amount, // 震动的幅度
            ShakeTime = time // 震动的持续时间
        });
    }

    // 震动请求类,用于存储一个震动请求的幅度和持续时间
    private class ShakeRequest
    {
        public float ShakeAmount { get; set; } // 请求的震动幅度
        public float ShakeTime { get; set; } // 请求的震动持续时间
    }
}

挂载点击事件,配置参数,b的振幅比a大

效果,大的震动会替换小的震动效果,而且无限震动

清除震动

都按预期工作现在我们需要以某种方式

基本上清除震动以摆脱

那些不应该再存在的震动,

修改脚本

csharp 复制代码
[SerializeField]
private float _shakeDecreaseAmount = 10f;// 震动幅度减少的速率,每秒减少的幅度

private void Update()
{
	//。。。

	// 遍历所有的震动请求
    for (var i = _requests.Count - 1; i >= 0; i--)
    {
        var request = _requests[i];

        // 减少震动请求的持续时间
        request.ShakeTime -= Time.deltaTime;

        // 如果震动请求的持续时间小于等于0,开始减少震动幅度
        if (request.ShakeTime <= 0)
        {
            request.ShakeAmount = Mathf.Max(0, request.ShakeAmount - Time.deltaTime * _shakeDecreaseAmount);
        }

        // 如果震动幅度已经减少到0,从列表中移除该震动请求
        if (request.ShakeAmount == 0) _requests.Remove(request);
    }
}

效果,震动一会,消失

控制震动的幅度和时间

新增脚本CameraShakeRequester,控制震动的幅度和时间

csharp 复制代码
using UnityEngine;

public class CameraShakeRequester : MonoBehaviour
{
    [SerializeField]
    private float _shakeAmount; // 请求震动的幅度

    [SerializeField]
    private float _shakeTime; // 请求震动的持续时间

    [SerializeField]
    private CameraShaker _shaker; // CameraShaker组件,用于控制相机震动效果

    // 请求相机震动
    public void RequestShake()
    {
        _shaker.RequestShake(_shakeAmount, _shakeTime);
    }
}

挂载脚本,配置参数,并重新修改配置A、B按钮的点击事件

效果

两个不同的强弱震动同时发生

我们A的震动调成振幅为1持续5秒,

B的震动调成振幅为10持续1秒

运行效果,你会发现,当强弱震动同时产生时,强震动先覆盖弱震动,强震动完成后,再继续执行剩下时间的弱震动,它们能够很好地协同工作

源码

整理好了,我会放上来

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。点赞越多,更新越快哦!当然,如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

相关推荐
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
_oP_i5 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
代码盗圣8 小时前
GODOT 4 不用scons编译cpp扩展的方法
游戏引擎·godot
lrlianmengba10 小时前
推荐一款可视化和检查原始数据的工具:RawDigger
人工智能·数码相机·计算机视觉
CV-X.WANG13 小时前
【详细 工程向】基于Smart3D的五镜头相机三维重建
数码相机·3d
Leoysq14 小时前
【UGUI】实现点击注册按钮跳转游戏场景
游戏·unity·游戏引擎·ugui
PandaQue15 小时前
《潜行者2切尔诺贝利之心》游戏引擎介绍
游戏引擎
_oP_i17 小时前
unity中 骨骼、纹理和材质关系
unity·游戏引擎·材质
小负不负18 小时前
使用kalibr_calibration标定相机(realsense)和imu(h7min)
数码相机·opencv·计算机视觉
Padid1 天前
Unity SRP学习笔记(二)
笔记·学习·unity·游戏引擎·图形渲染·着色器