UnityVR--AudioManager--音频管理中心

news2024/11/16 5:49:09

目录

前言

建立音频配置文件AudioConfig

建立音频管理AudioManager

使用AudioManager播放音效


前言

  关于音频组件的简单使用请详见VideoPlayer&AudioSource,不过在一个工程项目中,会有很多的声音文件,播放的时间和条件也不相同,因此在实际制作中,需要集中管理,这就是建立AudioManager的原因。

  先做好准备,下载好需要的声音片段,这里准备了背景音效bgm和走路音效step,存放到Assets/Resources/Audio文件夹下

建立音频配置文件AudioConfig

  1. 创建一个AudioConfig.cs脚本:

[CreateAssetMenu(fileName = "AudioConfig", menuName = "tang/AudioConfig", order = 1)]
public class AudioConfig : ScriptableObject //继承这个类,会将配置文件作为唯一的实例保存
{
    public string audioPath = "Audio/";  //音频的总路径,在Resources/Audio下
    [Range(0, 1)]
    public float mainVolume = 1;    //主音量
    [Range(0, 1)]
    public float effectVolume = 1;  //音效音量
    [Range(0, 1)]
    public float bgmVolume = 1;     //背景音乐音量
    public List<AudioData> audioLibrary;
}

  说明:(1)CreateAssetMenu用于在Project窗口中点右键的菜单中生成一个自己命名的菜单,这里生成一个AudioConfig菜单,用于配置AudioConfig类中的参数

   (2)ScriptableObject类,用于存储配置数据,详见ScriptableObject使用指南_YY-nb的博客

  2. AudioConfig类中的AudioData,定义了音效的设置参数,可以直接写在AudioConfig.cs脚本中:

[Serializable]  //将AudioData序列化,以便于在面板中看到
public struct AudioData
{
    //通过字符串找到相应的声音片段
    public string key;
    //音频资源文件
    public AudioClip clip;
    //音量控制属性
    [Range(0,1)]
    public float volume;
    //音频类型
    public EAudioType type;
}

  3. AudioData中的类型EAudioType,是一个枚举类型,定义了音效的类型,比如背景音效、跑步音效等

public enum EAudioType
{
    BGM,EFFECT
}

  4. 这样,在右键->tang->AudioConfig之后,就可以新建一个声音配置文件,在它的管理列表中点“+”号就可以添加一个新的音效片段的管理数据,这些数据将被放入AudioManager的字典中随时调用。

建立音频管理AudioManager

  在这里要设置对于背景音效、效果音等不同类型音的:播放、停止、调整音量等一些实用工具,根据项目的需要还可以设计一些其他的实用工具。这些都写在AudioManager.cs中,这是一个管理阶层的工具,同样继承于SingleMono单例,挂在场景中的SingleMono空节点上。

  1. 先定义一下管理中需要使用到的参数:建立一个播放背景音的声音源和一个播放音效的声音源,建立音量参数,以及一个字典用于存储声音片段及相关的数据:

public class AudioManager : SingleMono<AudioManager>
{
    public AudioSource bgmSource; //背景音声音源
    public GameObject effectSource;//音效声音源
    public AudioConfig audioConfig; //声音配置文件,自定义

    [Range(0, 1)] private float mainVolume = 1;    //总的音量,规定取值范围
    [Range(0, 1)] private float effectVolume = 1;  //音效音量
    [Range(0, 1)] private float bgmVolume = 1;     //背景音乐音量

    //定义一个字典用于存储音效名及需要传输的数据
    private Dictionary<string, AudioData> audioLibrary;

    void Awake()
    {
        audioLibrary= new Dictionary<string, AudioData>();
        foreach(var data in audioConfig.audioData)
        {//遍历一下audioConfig中的audioData列表
            //将列表中的所有数据加入到字典中
            audioLibrary.Add(data.key, data);
        }
        mainVolume = audioConfig.mainVolume; //把在面板中设置的音量值加载进来
        effectVolume = audioConfig.effectVolume;
        bgmVolume = audioConfig.bgmVolume;
    }
}

  这需要在场景中设置两个空节点,bgmSource和effectSource,bgmSource中加入AudioSource组件,effectSource节点空着。并将它们和上面的AudioConfig文件拖入到相应的三个public变量中:

 

   2. 加入播放BGM的一些工具,这里只是列举了一些,当需要其他的BGM控制工具时再来增加:

    //播放背景音效
    public void PlayBGM(string key, bool isLoop, Action onComplete = null)
    {//通过key找到字典中相应的数据,是否循环,播放完毕后回调
        AudioData data;
        if (!audioLibrary.TryGetValue(key, out data))
        {//字典中没有找到该key 
            Debug.LogError("音频:" + key + "播放出错!");
            return;
        }
        float volume = mainVolume + data.volume + bgmVolume;//最终音量
        //使用AudioSource的API设置并播放音效
        bgmSource.clip = data.clip;
        bgmSource.loop = isLoop;
        bgmSource.volume = volume;
        bgmSource.Play();//使用AudioSource的API-Play()播放音效
    }
    //使用AudioSource的API暂停和取消暂停
    public void PauseBGM()
    {
        bgmSource.Pause();
    }
    public void unPauseBGM()
    {
        bgmSource.UnPause();
    }
    public void changeBGMVolume(float volume)
    {//修改音量值,传入一个音量系数
        bgmSource.volume = bgmSource.volume / bgmVolume * volume;
        bgmVolume = volume;
    }
    public void ResetBGMVolume()
    {//重置音量
        bgmSource.volume = bgmSource.volume / bgmVolume * audioConfig.bgmVolume;
        bgmVolume = audioConfig.bgmVolume;
    }
    public void StopBGM(Action onComplete = null)
    {//停止播放
        bgmSource.Stop();
        bgmSource.clip = null;
        onComplete?.Invoke(); //回调
    }

   3. 加入播放其他音效的一些办法,也包括了上面这些方法,有所不同的是,背景音乐同时播放的只有一个,而音效可能会播放多个。因此音效的AudioSource组件需要动态添加,需要播放几个音效就要添加几个组件:

    public AudioSource PlayEffect(string key, bool isloop)
    {//播放音效
        AudioData data;
        if (!audioLibrary.TryGetValue(key, out data))
        {
            Debug.LogError("音频:" + key + "播放音效出错!");
            return default;
        }
        float volume = mainVolume * data.volume * effectVolume;//最终音效音量计算

        //音效有可能会同时播放多个,所以AudioSource组件有可能加载多个
        AudioSource[] sources = effectSource.GetComponents<AudioSource>();

        //是否找到空闲的AudioSource组件
        bool bTmp = false;
        foreach(var audios in sources)
        {
            if(!audios.isPlaying)  //如果这个AudioSource不在播放状态
            {
                audios.clip = data.clip;
                audios.loop = isloop;
                audios.volume = volume;
                bTmp = true;        //将判断改为在用状态
                audios.Play();      //开始播放音效
                return audios;      //播放完成之后,将值返回出去
            }
        }

        if (!bTmp)
        {
            var source = effectSource.AddComponent<AudioSource>();  //如果没有找到空闲的AudioSource则增加一个
            source.clip = data.clip;
            source.loop = isloop;
            source.volume = volume;
            source.Play();
            return source;
        }
        return default;
    }

使用AudioManager播放音效

  定义一个Test.cs随意挂在场景

public class Test : MonoBehaviour
{
    // 播放音频
    void Start()
    {
        AudioManager.Instance.PlayBGM("BGM", true); //播放背景音效
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))  //按下T键时播放音效
        {
            AudioManager.Instance.PlayEffect("Step", false);
        }
    }
}

  相应的AudioConfig设置:

   效果就不放了,声音播放也没有办法展示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法题】2614. 对角线上的质数

题目&#xff1a; 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&#xff0c;返回 0 。 注意&#xff1a; 如果某个整数大于 1 &#xff0c;且不存在除 1 和自身之外的正整数因子&#xff0c;…

Docker环境下部署Ghost开源内容管理系统

Docker环境下部署Ghost开源内容管理系统 一、Ghost介绍1.1 Ghost简介1.2 Ghost特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Ghost镜像五、部署Ghost开源内容管理系统…

【linux工具备忘录】- tmux

文章目录 安装常用命令会话的进入和退出窗口创建、删除、切换窗口内的子窗口管理(创建/删除/切换)会话的后台托管管理 tmux的配置配置的创建配置重载修改前缀键更多使用说明 tmux的插件管理tpm插件管理器tmux-powerline 一个漂亮的底栏 安装 sudo apt install tmux常用命令 会…

分布式软件架构——RESTful服务

RESTful&#xff08;Representational State Transfer&#xff09; RESTful是一种网络应用程序的设计风格和开发方式&#xff0c;基于HTTP&#xff0c;可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景&#xff0c;实现第三方OTT调用移动网…

shell脚本基础2——条件语句、分支选择、循环语句

文章目录 一、条件语句二、分支选择三、循环语句3.1 for循环3.1.1 语法一3.1.2 语法二 3.2 while循环3.2.1 普通用法3.2.2 whileif判断循环3.2.3 特殊用法 3.3 until循环 四、break和continue4.1 break用法4.2 continue用法 五、自定义脚本退出状态码 一、条件语句 使用 if 语句…

XdsObjects .NET 8.45.1001.0 Crack

XdsObjects 是一个工具包&#xff0c;允许开发人员使用 IHE XDS 和 XDS-I 配置文件开发应用程序&#xff0c;只需花费最少的时间和精力&#xff0c;因为遵守配置文件和 ebXML 规则的所有艰苦工作都由该工具包处理。 它为所有角色提供客户端和服务器支持&#xff0c;包括&#…

【Spring MVC】学会这些你就会利用Spring Boot进行前后端交互了,美滋滋,距离编程世界更近一步了,何乐而不为呢 ? ? ?

前言: 大家好,我是良辰丫,! ! !&#x1f48c;&#x1f48c;&#x1f48c; &#x1f9d1;个人主页&#xff1a;良辰针不戳 &#x1f4d6;所属专栏&#xff1a;javaEE进阶篇之框架学习 &#x1f34e;励志语句&#xff1a;生活也许会让我们遍体鳞伤&#xff0c;但最终这些伤口会成…

【仪器使用操作笔记】 TDS1012示波器基础原理与使用

今日要学习使用的是一台实验室老旧战损版TDS1012示波器&#xff0c;它长这样&#xff1a; 本文会从以下目录的几个方面全方位介绍示波器的一些基础运用&#xff1a; 目录 一、面板按键旋钮介绍&#xff1a; 整体面板介绍&#xff1a; 示波器探头接线与校准接线&#xff1a; …

一文弄懂java中的代理模式

文章目录 简介静态代理动态代理Cglib代理spring中AOP使用代理总结 简介 代理(Proxy)模式是一种结构型设计模式&#xff0c;提供了对目标对象另外的访问方式&#xff1b;即通过代理对象访问目标对象。 这样做的好处是&#xff1a;可以在目标对象实现的基础上&#xff0c;增强额…

Atcoder Beginner Contest 305——D-F题讲解

蒟蒻来讲题&#xff0c;还望大家喜。若哪有问题&#xff0c;大家尽可提&#xff01; Hello, 大家好哇&#xff01;本初中生蒟蒻讲解一下AtCoder Beginner Contest 305这场比赛的D-F题&#xff01; D题 题外话 安利一波自己的洛谷博客&#xff1a;点这里 思路 这道题还是比…

Hazel游戏引擎(010)预编译头

文中若有代码、术语等错误&#xff0c;欢迎指正 文章目录 前言如何实现 前言 此节目的 由于项目中的头文件或者cpp文件都包含着c的头文件&#xff0c;有些重复&#xff0c;可以将它们包含的c头文件放在一个头文件内&#xff0c;这样不仅使代码简洁&#xff0c;而且预编译头可以…

算法刷题-哈希表-两个数组的交集

两个数组的交集 349. 两个数组的交集思路拓展后记其他语言版本相关题目 如果哈希值比较少、特别分散、跨度非常大&#xff0c;使用数组就造成空间的极大浪费&#xff01; 349. 两个数组的交集 力扣题目链接 题意&#xff1a;给定两个数组&#xff0c;编写一个函数来计算它们的…

Java集合框架:ArrayList详解

目录 一、ArrayList简介 二、ArrayList源码介绍&#xff08;动态扩容以及构造方法是如何实现的&#xff09; 1. 扩容机制&#xff1a; 源码&#xff1a; 源码详解&#xff1a; ​编辑 如何扩容&#xff1a; 2. 扩容源码详解&#xff1a; 三、ArrayList的构造方法 四、ArrayL…

【Linux运维】GitLab本地服务器搭建

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍gitlab本地服务器的搭建。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习知识&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新…

【JVM内存模型】—— 每天一点小知识

&#x1f4a7; J V M 内存模型 \color{#FF1493}{JVM内存模型} JVM内存模型&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 《数据结构与算法》专栏的文章图文并茂&#x…

MyBatis-plus(2)

实现逻辑查询: 1)and:其实如果只是想实现and查询&#xff0c;只是需要连续调用对应的方法或者是通过wrapper对象实现两次调用即可 2)and的嵌套:假设现在有这样一条语句 select * from user where username"张三" and (age>26 or userID <19)&#xff0c;这条SQ…

使用django的APP在前端上传excel通过post传给后端读取并打印

文章目录 前言前端后端 前言 备研了&#xff0c;博客许久未更了&#xff0c;但是学期末的大作业&#xff0c;遇到了问题并成功解决了&#xff0c;不得不记录一下。 前端 <form method"post" enctype"multipart/form-data" action"/insurance/up…

Hazel游戏引擎(011)窗口抽象和GLFW创建窗口

文中若有代码、术语等错误&#xff0c;欢迎指正 文章目录 前言步骤GIT添加GLFW子模块及编译Window类其它修改 效果Bug记录 前言 此节目的 为了有窗口效果&#xff0c;但不想使用原生的window32写起&#xff0c;所以用glfw窗口库。 也为了完成008计划事件系统的创建窗口部分 图…

AI数据标注工具Doccano

Doccano是一款开源的标注工具&#xff0c;用于自然语言处理和机器学习任务。它提供了用户友好的界面&#xff0c;使用户能够轻松地标注文本、序列标注、文本分类和文本配对等任务。doccano支持多种标注格式&#xff0c;并且可以方便地与其他机器学习工具集成。它的简单性和灵活…

基于 MySQL 事务、隔离级别及 MVCC 机制详细剖析

前言事务特性事务并发引发的问题脏读不可重复读幻读 隔离级别如何更改事务隔离级别 事务基本操作MVCC版本链ReadViewREAD COMMITTED脏读问题不可重复读问题 REPEATABLE READ不可重复读问题幻读问题 小结 总结 前言 MySQL 事务是比较重要且核心的一部分&#xff0c;在操作数据库…