unity全局音量管理/全局音量设置与音量设置界面(含静音功能)
前言
本文将会介绍如何使用audiomixer实现全局音量控制,并且会介绍如何实现游戏内的含静音功能的音量设置界面。
本人也是个初学者,在看过一些关于音量管理的教程后,发现使用audiomixer实现全局音量控制可能是最方便、功能最完备、强大的,因此在这里分享一下自己的实现方法。如果有错误,还请指出捏
基础
音效成功播放需要两个先决条件:音频源 (Audio Source) 和 音频监听器 (Audio Listener)。
音频源 (Audio Source) 在场景中播放音频,而音频监听器 (Audio Listener) 充当类似于麦克风的设备。它接收来自场景中任何给定音频源的输入,并通过计算机扬声器播放声音。

AudioListener和AudioSource
其中,Audio Listener 会在相机创建时自动创建,当同一场景中的Audio Listener数量大于1时,unity编辑器会报错
而混音器 (Audio Mixer) 允许混合各种音频源,对音频源应用效果。在音频源脚本(Audio Source)的Output挂载AudioMixer的Group Controller文件后,这个音频源就会放出应用了AudioMixer效果的音频。基于此,通过使用代码对AudioMixer的音量进行动态调整,我们就可以实现游戏内动态调整这一个音频源的音量,进而调整全局音量了。
逻辑:
游戏中的音频大致可分为 音效(Sound) 和音乐(Music)两种,因此我们这里就只实现对音效和音乐的设置,同时实现对主音量(Master)的设置

逻辑关系
AudioMixer制作
1.create->AudioMixer
2.打开AudioMixer

这个NewAudioMixer就是新建的AudioMixer
3.点击Group的加号创建Music、Sound,并设置好层级关系

需要拖动,将三个group的层级关系设置为如图所示
4.在每个group的inspector中右键Volume,并将volume属性暴露出去
5.如图所示,重命名暴露出去的volume属性
至此,AudioMixer就基本完成了。将AudioMixer文件夹下的Audio Mixer Group Controller文件拖动到AudioSource的Output中,这个AudioSource放出的音频就都将会应用对应Group的效果。
下面,我们就可以通过动态设置刚才暴露出的volume属性来实现音量设置了。开始愉快的写代码吧~
音量设置面板实现
在这里,我简单地假设开发情形如下:有两个场景,每个场景播放不同的背景音乐。那么,就只需要在两个场景中创建两个搭载了AudioSource,并循环播放bgm的空物体,即可实现播放背景音乐的需求

如图所示
而音效的播放,则是在所有场景中都会频繁地使用到,并且播放的音效各不相同,因此需要创建一个用于播放音效的持续单例脚本,使其在场景切换时不被摧毁,并且便于其他脚本调用播放音效的脚本,满足整个游戏的音效播放需求。
至于音量设置,由常理可知音量是全局均可设置的,因此也使用持续单例模式开发,并且用滑动条(sliider)来调节音量。
同时:我们需要实现音量设置面板的如下功能:
1.静音按钮
2.取消静音时回调滑动条到未静音时的值
那么,我们将这一个功能的实现分为两个部分:持续单例AudioManager,以及一个继承了monobehavior的脚本,用于控制其所处场景的音量ui。
AudioManager脚本
(我偷懒,就把播放音效功能和AudioManager脚本写到一起了,虽然这样不会有什么大问题,但二者终究不是同一个功能,可能会导致代码比较混乱)
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;//使用单例模式开发,继承单例父类,使其在场景切换时不销毁
//同时包括音量设置功能和播放音效功能
public class AudioManager : PersistentSingleton<AudioManager>
{[SerializeField] AudioMixer audioMixer;//改变音调const float pitchMin = 0.9f;const float pitchMax = 1.1f;//用于判断静音与否private bool IsMuteMaster = false;private bool IsMuteMusic = false;private bool IsMuteSound = false;//用于储存静音前的音量private float LastMaster;private float LastMusic;private float LastSound;//音量设置//Slider on click:调节音量,若静音则取消静音public void MasterSldOnClick(GameObject image, Slider slider){audioMixer.SetFloat("vMaster", slider.value);if (IsMuteMaster == false) return;else{image.SetActive(false);IsMuteMaster = false;}}public void MusicSldOnClick(GameObject image, Slider slider){audioMixer.SetFloat("vMusic", slider.value);if (IsMuteMusic == false) return;else{image.SetActive(false);IsMuteMusic = false;}}public void SoundSldOnClick(GameObject image, Slider slider){audioMixer.SetFloat("vSound", slider.value);if (IsMuteSound == false) return;else{image.SetActive(false);IsMuteSound = false;};}//Button on click:若静音则取消静音并回调音量;若未静音则静音并储存音量public void MasterBtnOnClick(GameObject image, Slider Master){if (IsMuteMaster){image.SetActive(false);IsMuteMaster = false;Master.value = LastMaster;}else{image.SetActive(true);LastMaster = Master.value;Master.value = Master.minValue;IsMuteMaster = true;}}public void SoundBtnOnClick(GameObject image, Slider Sound){if (IsMuteSound){image.SetActive(false);IsMuteSound = false;Sound.value = Instance.LastSound;}else{image.SetActive(true);LastSound = Sound.value;Sound.value = Sound.minValue;IsMuteSound = true;}}public void MusicBtnOnClick(GameObject image, Slider Music){if (IsMuteMusic){image.SetActive(false);IsMuteMusic = false;Music.value = LastMusic;}else{image.SetActive(true);LastMusic = Music.value;Music.value = Music.minValue;IsMuteMusic = true;}}[SerializeField] AudioSource SoundPlayer;//播放音效public void PlaySound(AudioClip audioClip){SoundPlayer.pitch = 1;SoundPlayer.PlayOneShot(audioClip);}// 改变音调,主要用于重复播放的音效public void PlayRandomSound(AudioClip audioClip){SoundPlayer.pitch = Random.Range(pitchMin , pitchMax );SoundPlayer.PlayOneShot(audioClip);}public void PlayRandomSound(AudioClip[] audioClip){PlayRandomSound(audioClip[Random.Range(0, audioClip.Length)]);}
}
其中 ,PersistentSingleton为持续泛型单例父类,使脚本挂载的物体不随场景改变而销毁,并且使其他脚本更容易调用本脚本内容。代码见下,详情可见unity单例,实现全局保存/跨场景传输数据
using UnityEngine;public class PersistentSingleton<T> : MonoBehaviour where T : Component
{public static T Instance { get; private set; }protected virtual void Awake(){if (Instance == null){Instance = this as T;}else if (Instance != this){Destroy(gameObject);}DontDestroyOnLoad(gameObject);}
}
写完AudioManager脚本后,将AudioManager挂载到一个第一个场景的空物体上,以便生效(或是挂载到可以调节音量的第一个场景也行)。然后再将刚做好的AudioMixer和用于播放音效的AudioSource拖进脚本里面就行了~

AudioSource和AudioManager如上图所示
在这种实现方式下,需要把AudioSource放在AudioManager下,防止跨场景销毁。但这是基于只用这一个音源就可满足整个游戏音效需求的大前提下的,可能会有更好的实现方法。
AudioManager是全局起作用的,只需要在调节滑动条(slider)时调用三个SldOnClick函数/点击按钮时调用三个BtnOnClick函数,即可以实现全局调节音量的功能。
不过值得注意的是,三个BtnOnClick函数中有一条命令:Sound.value = Instance.LastSound。这条命令不会导致bug,会正常触发SldOnClick,因为SldOnClick的触发条件实际上是On Value Change(所有slider都是),只要值变化就可以触发,而并非一定要click。
各场景音量设置界面,以及设置界面脚本
下面,我们需要为每个场景创建音量设置界面,这里只创建一个场景的,因为其他场景也是一样的,实际开发时复制粘贴就行。
1.滑动条(slider)
slider组件比较复杂,虽然不难,但是创建一个功能完备的slider也不是一两句就能说完的,这里时跳过,不懂的小伙伴可以去找些教程,先创建一个能用的滑动条。

2.音量设置界面

按照上图思路,继续创建音效和音乐的设置界面。
3.设置界面脚本
using UnityEngine;
using UnityEngine.UI;public class TestScene : MonoBehaviour
{[Header("-----音量设置条-----")][SerializeField] Slider Master;[SerializeField] Slider Music;[SerializeField] Slider Sound;//SldOnClick:传递参数以触发AudioManager的SldOnClickpublic void MasterSldOnClick(GameObject image){AudioManager.Instance.MasterSldOnClick(image, Master);}public void MusicSldOnClick(GameObject image){AudioManager.Instance.MusicSldOnClick(image, Music);}public void SoundSldOnClick(GameObject image){AudioManager.Instance.SoundSldOnClick(image, Sound);}//BtnOnClick:传递参数以触发AudioManager的BtnOnClickpublic void MasterBtnOnClick(GameObject image){AudioManager.Instance.MasterBtnOnClick(image, Master);}public void SoundBtnOnClick(GameObject image){AudioManager.Instance.SoundBtnOnClick(image, Sound);}public void MusicBtnOnClick(GameObject image){AudioManager.Instance.MusicBtnOnClick(image, Music);}}
这个脚本实际上只是起到了传递参数的作用,这么做一方面时因为,多个参数的函数不能挂载到button、slider等组件上,另一方面是因为, AudioManager是持续单例,在某些场景中不是初始存在,无法直接挂载到组件上,需要使用代码动态调用。
将这个脚本挂载到场景中(随便哪都行),并将三个slider挂载到脚本上即可。
3.配置按键与滑动条
以Master按键和滑动条为例:

将刚才设置好的脚本挂到button组件下,并选择MasterBtnOnClick函数,将按键的子物体image挂到这个函数下面

Sound、Music同上
同样的,给Master的slider挂上 MasterSldOnClick函数,同样的把Master的叉号挂到函数下即可。
至此,整个音量设置界面就做完了
相关文章:
unity全局音量管理/全局音量设置与音量设置界面(含静音功能)
前言 本文将会介绍如何使用audiomixer实现全局音量控制,并且会介绍如何实现游戏内的含静音功能的音量设置界面。 本人也是个初学者,在看过一些关于音量管理的教程后,发现使用audiomixer实现全局音量控制可能是最方便、功能最完备、强大的&a…...
C++ vector 数组转换、查找、最大最小值、排序、排行的几种用法
C vector中常用到排序、取最值,一些场景可能还会要计算某个元素的排行,以下就是一些实际例子,精简、有效。 【1】会涉及到数组转vector: vector<int> v(arr, arr N); // N为数组size,可用sizeof(arr)/sizeof(i…...
vmware 安装Rocky-9.3系统
安装系统截图 安装完成,启动 查看版本和内核 开启远程登陆授权 1、编辑配置文件 #提升权限,输入su,并输入密码 su #编辑ssh文件开启root远程登陆 vi /etc/ssh/sshd_config找到以下内容:#PermitRootLogin prohibit-password 添加:…...
C++提高编程——模板
本专栏记录C学习过程包括C基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下,不定时更新,欢迎关注。 当前章节处于: ---------第1阶段-C基础入门 ---------第2阶段实战…...
单线程、同步、异步、预解析、作用域、隐式全局变量、对象创建、new
单线程 进程 cpu 资源分配的最小单位一个进程可以有多个线程 线程 cpu调度的最小单位线程建立在进程的建立基础上的一次程序的运行单位 线程分为:单线程 多线程 单线程:js是单线程 (同一个时间只能完成一个任务)多线程&…...
《设计模式的艺术》笔记 - 外观模式
介绍 外观模式中外部与一个子系统的通信通过一个统一的外观角色进行,为子系统中的一组接口提供一个一致的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。 实现 myclas…...
sql 查询时间范围内的数据
要查询特定时间范围内的数据,您可以使用 SQL 中的 BETWEEN 运算符。以下是一个示例查询,它从名为 your_table 的表中检索在 start_date 和 end_date 之间创建的所有记录: SELECT * FROM your_table WHERE created_date BETWEEN start_date AN…...
TestNG中的@BeforeSuite注释
目录 什么是BeforeSuite注解? BeforeSuite带注释的方法何时执行? BeforeSuite annotation有什么用? 所以,是时候集思广益了 我们可以在一个类中使用多个BeforeSuite注释方法吗? BeforeSuite放在超类上时如何工作…...
[学习笔记]刘知远团队大模型技术与交叉应用L3-Transformer_and_PLMs
RNN存在信息瓶颈的问题。 注意力机制的核心就是在decoder的每一步,都把encoder的所有向量提供给decoder模型。 具体的例子 先获得encoder隐向量的一个注意力分数。 注意力机制的各种变体 一:直接点积 二:中间乘以一个矩阵 三:…...
图像处理工具包Pillow的使用分享
Pillow 是 Python 中一个流行的图像处理库,它是 PIL(Python Imaging Library)的一个友好的分支版本。Pillow 提供了许多功能,使得图像处理变得容易和方便。下面是一些基本用法和示例: 安装 Pillow 首先,你…...
python进程间通信——命名管道(Named Pipe、FIFO)
文章目录 Python中的命名管道:深入理解进程间通信1. 命名管道简介2. 创建和删除命名管道3. 写入命名管道4. 读取命名管道5. 示例:进程间通信write_to_pipe.pyread_from_pipe.py测试运行 6. 注意事项和限制命名管道的半双工机制命名管道读写任意一方未打开…...
03 OSPF 学习大纲
参考文章 1 初步认识OSPF的大致内容(第三课)-CSDN博客 2...
HJ7 取近似值【C语言】
【华为机试题 HJ7】取近似值 描述输入描述:输出描述:示例1示例2参考代码1参考代码2参考代码3描述 写出一个程序,接受一个正浮点数值,输出该数值的近似整数值。如果小数点后数值大于等于 0.5 ,向上取整;小于 0.5 ,则向下取整。 数据范围:保证输入的数字在 32 位浮点数范…...
php基础学习之常量
php常量的基本概念 常量是在程序运行中的一种不可改变的量(数据),常量一旦定义,通常不可改变(用户级别)。 php常量的定义形式 使用define函数:define("常量名字", 常量值);使用cons…...
2024最新面试经验分享
目录 重点掌握的知识点JavaMySQLRedis 微服务分布式系统项目亮点场景题/设计题短链抢红包多租户 开放性问题自我介绍为什么跳槽团队规模如何带团队如何看待加班职业规划 主要针对Java程序员,当然也包含一些通用的内容。 重点掌握的知识点 需要重点掌握的知识点必须…...
《WebKit 技术内幕》之八(1):硬件加速机制
《WebKit 技术内幕》之八(1):硬件加速机制 1 硬件加速基础 1.1 概念 这里说的硬件加速技术是指使用GPU的硬件能力来帮助渲染网页,因为GPU的作用主要是用来绘制3D图形并且性能特别好,这是它的专长所在,它…...
子表单扫码录入,显著节省填写时间
01/17 主要更新模块概览 扫 码 识 别 新 增 字 号 登 录 配 置 匹 配 搜 素 扫码识别 路径:表单设计 >> 字段属性 功能简介 之前对子表单扫码录入,是单独在组件内设置扫码,操作需重新点击扫码功能,手工新增子表数据&a…...
【Redis】Ubuntu安装配置
目录 一、安装Redis 1.1 从APT仓库安装Redis 二、启动&关闭&重启 三、Redis核心配置 3.1 CONFIG命令 3.2 redis.conf文件说明 一、安装Redis 1.1 从APT仓库安装Redis 从APT仓库可以安装最新的Redis稳定版,步骤如下: 【1】安装需要用到的…...
idea远程服务调试
1. 配置idea远程服务调试 这里以 idea 新 ui 为例,首先点击上面的 debug 旁边的三个小圆点,然后在弹出的框框中选择 “Edit”,如下图所示。 然后进入到打开的界面后,点击左上角的 “” 进行添加,找到 “Remote JVM De…...
Google Colab运行Pytorch项目
Google Colab运行Pytorch项目 连接google drive切换到某一文件夹显示当前目录文件安装依赖执行py文件numpy相关numpy.random.randn() 参考文章:文章1 文章2 连接google drive from google.colab import drive import os drive.mount(/content/drive)切换到某一文件…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
