欢迎加入Unity业内qq交流群:956187480

qq扫描二维码加群,行业纵横颇多,每个人精通领域各异,旨在交流,


在项目里做音频管理的时候,我们往往是跟资源管理结合起来的,但是这里我们就单音频管理展开。其实音频管理无非就是对几种固定的音效类型进行加载,播放,暂停,调音等一系列操作。我们只需要把一些常规操作写出来满足大部分的需求即可,对于其他一些特殊功能的比如在线剪切片段,动态调整音素的就需要我们另外实现。

我们一般会把音频分为四类:以农场类项目为例

1.背景音乐:全局只有一个,不同的场景不同的时间不同的天气都会有不同的背景音乐,其主要作用是为了烘托氛围。所以大部分的背景音乐都是2d的且音量是所有音效中最低的,目的为不突兀不刺激为主。

// 播放背景音乐
public void PlayBackgroundMusic(AudioClip clip, bool isLoop = true, float speed = 1)
// 暂停播放背景音乐
public void PauseBackgroundMusic(bool isGradual = true)

2.人声配音:全局只有一个,经常会用在人物对话,npc讲话等人声场景下。当播放新的声音时会把当前的声音覆盖掉。

/// 播放单通道音效
public void PlaySingleSound(AudioClip clip, bool isLoop = false, float speed = 1)
/// 暂停播放单通道音效
public void PauseSingleSound(bool isGradual = true)

3.技能ui音效:全局可以多个,在触发ui的时候或者释放技能的时候我们的配音是可以多个可重叠的。

/// 播放多通道音效public void PlayMultipleSound(AudioClip clip, bool isLoop = false, float speed = 1)/// 停止播放指定的多通道音效public void StopMultipleSound(AudioClip clip)

4.世界3d音效:全局可以多个,世界音效其实就是3d音,我们一般用在固定位置范围内的音效,通过设置触发距离听到音量不一样的空间声音,比如cf的敌人脚步声。

 /// 播放世界音效
public void PlayWorldSound(GameObject attachTarget, AudioClip clip, bool isLoop = false, float speed = 1)
/// 暂停播放指定的世界音效public void PauseWorldSound(GameObject attachTarget, bool isGradual = true)

源代码:

using DG.Tweening;
using System.Collections.Generic;
using UnityEngine;public delegate void AudAction();
/// <summary>
/// 音频管理者
/// </summary>
[DisallowMultipleComponent]
public sealed class AudioManager : MonoBehaviour
{/// <summary>/// 是否静音初始值【请勿在代码中修改】/// </summary>public bool MuteDefault = false;/// <summary>/// 背景音乐优先级初始值【请勿在代码中修改】/// </summary>public int BackgroundPriorityDefault = 0;/// <summary>/// 单通道音效优先级初始值【请勿在代码中修改】/// </summary>public int SinglePriorityDefault = 10;/// <summary>/// 多通道音效优先级初始值【请勿在代码中修改】/// </summary>public int MultiplePriorityDefault = 20;/// <summary>/// 世界音效优先级初始值【请勿在代码中修改】/// </summary>public int WorldPriorityDefault = 30;/// <summary>/// 背景音乐音量初始值【请勿在代码中修改】/// </summary>public float BackgroundVolumeDefault = 0.6f;/// <summary>/// 单通道音效音量初始值【请勿在代码中修改】/// </summary>public float SingleVolumeDefault = 1;/// <summary>/// 多通道音效音量初始值【请勿在代码中修改】/// </summary>public float MultipleVolumeDefault = 1;/// <summary>/// 世界音效音量初始值【请勿在代码中修改】/// </summary>public float WorldVolumeDefault = 1;/// <summary>/// 单通道音效播放结束事件/// </summary>public event AudAction SingleSoundEndOfPlayEvent;private AudioSource _backgroundAudio;private AudioSource _singleAudio;private List<AudioSource> _multipleAudios = new List<AudioSource>();private Dictionary<GameObject, AudioSource> _worldAudios = new Dictionary<GameObject, AudioSource>();private bool _singleSoundPlayDetector = false;private bool _isMute = false;private int _backgroundPriority = 0;private int _singlePriority = 10;private int _multiplePriority = 20;private int _worldPriority = 30;private float _backgroundVolume = 0.6f;private float _singleVolume = 1;private float _multipleVolume = 1;private float _worldVolume = 1;public void Awake(){_backgroundAudio = CreateAudioSource("BackgroundAudio", BackgroundPriorityDefault, BackgroundVolumeDefault, 1, 0);_singleAudio = CreateAudioSource("SingleAudio", SinglePriorityDefault, SingleVolumeDefault, 1, 0);Mute = MuteDefault;BackgroundPriority = BackgroundPriorityDefault;SinglePriority = SinglePriorityDefault;MultiplePriority = MultiplePriorityDefault;WorldPriority = WorldPriorityDefault;BackgroundVolume = BackgroundVolumeDefault;SingleVolume = SingleVolumeDefault;MultipleVolume = MultipleVolumeDefault;WorldVolume = WorldVolumeDefault;}public void Start(){StopBackgroundMusic();StopSingleSound();StopAllMultipleSound();StopAllWorldSound();}public void Update(){if (_singleSoundPlayDetector){if (!_singleAudio.isPlaying){_singleSoundPlayDetector = false;SingleSoundEndOfPlayEvent?.Invoke();}}}/// <summary>/// 静音/// </summary>public bool Mute{get{return _isMute;}set{if (_isMute != value){_isMute = value;_backgroundAudio.mute = _isMute;_singleAudio.mute = _isMute;for (int i = 0; i < _multipleAudios.Count; i++){_multipleAudios[i].mute = _isMute;}foreach (var audio in _worldAudios){audio.Value.mute = _isMute;}}}}/// <summary>/// 背景音乐优先级/// </summary>public int BackgroundPriority{get{return _backgroundPriority;}set{if (_backgroundPriority != value){_backgroundPriority = value;_backgroundAudio.priority = _backgroundPriority;}}}/// <summary>/// 单通道音效优先级/// </summary>public int SinglePriority{get{return _singlePriority;}set{if (_singlePriority != value){_singlePriority = value;_singleAudio.priority = _singlePriority;}}}/// <summary>/// 多通道音效优先级/// </summary>public int MultiplePriority{get{return _multiplePriority;}set{if (_multiplePriority != value){_multiplePriority = value;for (int i = 0; i < _multipleAudios.Count; i++){_multipleAudios[i].priority = _multiplePriority;}}}}/// <summary>/// 世界音效优先级/// </summary>public int WorldPriority{get{return _worldPriority;}set{if (_worldPriority != value){_worldPriority = value;foreach (var audio in _worldAudios){audio.Value.priority = _worldPriority;}}}}/// <summary>/// 背景音乐音量/// </summary>public float BackgroundVolume{get{return _backgroundVolume;}set{if (!Mathf.Approximately(_backgroundVolume, value)){_backgroundVolume = value;_backgroundAudio.volume = _backgroundVolume;}}}/// <summary>/// 单通道音效音量/// </summary>public float SingleVolume{get{return _singleVolume;}set{if (!Mathf.Approximately(_singleVolume, value)){_singleVolume = value;_singleAudio.volume = _singleVolume;}}}/// <summary>/// 多通道音效音量/// </summary>public float MultipleVolume{get{return _multipleVolume;}set{if (!Mathf.Approximately(_multipleVolume, value)){_multipleVolume = value;for (int i = 0; i < _multipleAudios.Count; i++){_multipleAudios[i].volume = _multipleVolume;}}}}/// <summary>/// 世界音效音量/// </summary>public float WorldVolume{get{return _worldVolume;}set{if (!Mathf.Approximately(_worldVolume, value)){_worldVolume = value;foreach (var audio in _worldAudios){audio.Value.volume = _worldVolume;}}}}/// <summary>/// 播放背景音乐/// </summary>/// <param name="clip">音乐剪辑</param>/// <param name="isLoop">是否循环</param>/// <param name="speed">播放速度</param>public void PlayBackgroundMusic(AudioClip clip, bool isLoop = true, float speed = 1){if (_backgroundAudio.isPlaying){_backgroundAudio.Stop();}_backgroundAudio.clip = clip;_backgroundAudio.loop = isLoop;_backgroundAudio.pitch = speed;_backgroundAudio.Play();}/// <summary>/// 暂停播放背景音乐/// </summary>/// <param name="isGradual">是否渐进式</param>public void PauseBackgroundMusic(bool isGradual = true){if (isGradual){_backgroundAudio.DOFade(0, 2).OnComplete(() =>{_backgroundAudio.volume = BackgroundVolume;_backgroundAudio.Pause();});}else{_backgroundAudio.Pause();}}/// <summary>/// 恢复播放背景音乐/// </summary>/// <param name="isGradual">是否渐进式</param>public void UnPauseBackgroundMusic(bool isGradual = true){if (isGradual){_backgroundAudio.UnPause();_backgroundAudio.volume = 0;_backgroundAudio.DOFade(BackgroundVolume, 2);}else{_backgroundAudio.UnPause();}}/// <summary>/// 停止播放背景音乐/// </summary>public void StopBackgroundMusic(){if (_backgroundAudio.isPlaying){_backgroundAudio.Stop();}}/// <summary>/// 播放单通道音效/// </summary>/// <param name="clip">音乐剪辑</param>/// <param name="isLoop">是否循环</param>/// <param name="speed">播放速度</param>public void PlaySingleSound(AudioClip clip, bool isLoop = false, float speed = 1){if (_singleAudio.isPlaying){_singleAudio.Stop();}_singleAudio.clip = clip;_singleAudio.loop = isLoop;_singleAudio.pitch = speed;_singleAudio.Play();_singleSoundPlayDetector = true;}/// <summary>/// 暂停播放单通道音效/// </summary>/// <param name="isGradual">是否渐进式</param>public void PauseSingleSound(bool isGradual = true){if (isGradual){_singleAudio.DOFade(0, 2).OnComplete(() =>{_singleAudio.volume = SingleVolume;_singleAudio.Pause();});}else{_singleAudio.Pause();}}/// <summary>/// 恢复播放单通道音效/// </summary>/// <param name="isGradual">是否渐进式</param>public void UnPauseSingleSound(bool isGradual = true){if (isGradual){_singleAudio.UnPause();_singleAudio.volume = 0;_singleAudio.DOFade(SingleVolume, 2);}else{_singleAudio.UnPause();}}/// <summary>/// 停止播放单通道音效/// </summary>public void StopSingleSound(){if (_singleAudio.isPlaying){_singleAudio.Stop();}}/// <summary>/// 播放多通道音效/// </summary>/// <param name="clip">音乐剪辑</param>/// <param name="isLoop">是否循环</param>/// <param name="speed">播放速度</param>public void PlayMultipleSound(AudioClip clip, bool isLoop = false, float speed = 1){AudioSource audio = ExtractIdleMultipleAudioSource();audio.clip = clip;audio.loop = isLoop;audio.pitch = speed;audio.Play();}/// <summary>/// 停止播放指定的多通道音效/// </summary>/// <param name="clip">音乐剪辑</param>public void StopMultipleSound(AudioClip clip){for (int i = 0; i < _multipleAudios.Count; i++){if (_multipleAudios[i].isPlaying){if (_multipleAudios[i].clip == clip){_multipleAudios[i].Stop();}}}}/// <summary>/// 停止播放所有多通道音效/// </summary>public void StopAllMultipleSound(){for (int i = 0; i < _multipleAudios.Count; i++){if (_multipleAudios[i].isPlaying){_multipleAudios[i].Stop();}}}/// <summary>/// 销毁所有闲置中的多通道音效的音源/// </summary>public void ClearIdleMultipleAudioSource(){for (int i = 0; i < _multipleAudios.Count; i++){if (!_multipleAudios[i].isPlaying){AudioSource audio = _multipleAudios[i];_multipleAudios.RemoveAt(i);i -= 1;Destroy(audio.gameObject);}}}/// <summary>/// 播放世界音效/// </summary>/// <param name="attachTarget">附加目标</param>/// <param name="clip">音乐剪辑</param>/// <param name="isLoop">是否循环</param>/// <param name="speed">播放速度</param>public void PlayWorldSound(GameObject attachTarget, AudioClip clip, bool isLoop = false, float speed = 1){if (_worldAudios.ContainsKey(attachTarget)){AudioSource audio = _worldAudios[attachTarget];if (audio.isPlaying){audio.Stop();}audio.clip = clip;audio.loop = isLoop;audio.pitch = speed;audio.Play();}else{AudioSource audio = AttachAudioSource(attachTarget, WorldPriority, WorldVolume, 1, 1);_worldAudios.Add(attachTarget, audio);audio.clip = clip;audio.loop = isLoop;audio.pitch = speed;audio.Play();}}/// <summary>/// 暂停播放指定的世界音效/// </summary>/// <param name="attachTarget">附加目标</param>/// <param name="isGradual">是否渐进式</param>public void PauseWorldSound(GameObject attachTarget, bool isGradual = true){if (_worldAudios.ContainsKey(attachTarget)){AudioSource audio = _worldAudios[attachTarget];if (isGradual){audio.DOFade(0, 2).OnComplete(() =>{audio.volume = WorldVolume;audio.Pause();});}else{audio.Pause();}}}/// <summary>/// 恢复播放指定的世界音效/// </summary>/// <param name="attachTarget">附加目标</param>/// <param name="isGradual">是否渐进式</param>public void UnPauseWorldSound(GameObject attachTarget, bool isGradual = true){if (_worldAudios.ContainsKey(attachTarget)){AudioSource audio = _worldAudios[attachTarget];if (isGradual){audio.UnPause();audio.volume = 0;audio.DOFade(WorldVolume, 2);}else{audio.UnPause();}}}/// <summary>/// 停止播放所有的世界音效/// </summary>public void StopAllWorldSound(){foreach (var audio in _worldAudios){if (audio.Value.isPlaying){audio.Value.Stop();}}}/// <summary>/// 销毁所有闲置中的世界音效的音源/// </summary>public void ClearIdleWorldAudioSource(){HashSet<GameObject> removeSet = new HashSet<GameObject>();foreach (var audio in _worldAudios){if (!audio.Value.isPlaying){removeSet.Add(audio.Key);Destroy(audio.Value);}}foreach (var item in removeSet){_worldAudios.Remove(item);}}//创建一个音源private AudioSource CreateAudioSource(string name, int priority, float volume, float speed, float spatialBlend){GameObject audioObj = new GameObject(name);audioObj.transform.SetParent(transform);audioObj.transform.localPosition = Vector3.zero;audioObj.transform.localRotation = Quaternion.identity;audioObj.transform.localScale = Vector3.one;AudioSource audio = audioObj.AddComponent<AudioSource>();audio.playOnAwake = false;audio.priority = priority;audio.volume = volume;audio.pitch = speed;audio.spatialBlend = spatialBlend;audio.mute = _isMute;return audio;}//附加一个音源private AudioSource AttachAudioSource(GameObject target, int priority, float volume, float speed, float spatialBlend){AudioSource audio = target.AddComponent<AudioSource>();audio.playOnAwake = false;audio.priority = priority;audio.volume = volume;audio.pitch = speed;audio.spatialBlend = spatialBlend;audio.mute = _isMute;return audio;}//提取闲置中的多通道音源private AudioSource ExtractIdleMultipleAudioSource(){for (int i = 0; i < _multipleAudios.Count; i++){if (!_multipleAudios[i].isPlaying){return _multipleAudios[i];}}AudioSource audio = CreateAudioSource("MultipleAudio", MultiplePriority, MultipleVolume, 1, 0);_multipleAudios.Add(audio);return audio;}
}

欢迎加入Unity业内qq交流群:956187480

qq扫描二维码加群,行业纵横颇多,每个人精通领域各异,旨在交流,

【Unity开发小技巧】AudioManager声音管理器相关推荐

  1. 【Unity开发小技巧】FMS有限状态机详解

    欢迎加入Unity业内qq交流群:956187480 qq扫描二维码加群 在实际开发中很多时候对某类别的对象都需要有多种状态的管理和切换,这个时候我们就可以引入FMS状态机概念,有限状态机主要有三要素 ...

  2. 【Unity开发小技巧】Unity打包IOS端APP

    目录 一:安装IOS的模块并打包 1.Hub可以添加IOS模块 2.项目内部下载安装ISO模块 3.添加我们需要打包的场景 二:XCode工程内部设置并打包 1.mac商店安装XCode软件并打开xc ...

  3. Unity进阶第五章-声音管理器

    (1)创建Managers和AudioManager两个脚本 (2)AudioManager: using System.Collections; using System.Collections.G ...

  4. 【Unity开发小技巧】Unity日志输出存储

    一般我们在做项目的反馈日志收集的时候都会根据提交的后台日志判断线后Bug产生的大概原因,直接帮我们缩小范围. #region 模块信息 // ***************************** ...

  5. 【Unity开发小技巧】模型单指旋转双指缩放功能代码(多种情况)

    欢迎加入Unity业内qq交流群:956187480 qq扫描二维码加群 1.pc端通过鼠标中键调整相机的FieldOfView属性的值(会发生形变不建议) void Update(){if (Inp ...

  6. 【Unity开发小技巧】iOS APP下载安装时,如果出现此时无法下载安装APP的字样时,一些解决思路

    目录 一.OS系统和IOS版本更新 ​二:App-Store方式 三:Ad-hoc方式 四:In-house 方式 五: Architecture设置错误 六:App 支持的 iOS 系统版本,和当前 ...

  7. 【Unity开发小技巧】Unity随机概率扩展(概率可调控)

    做了以下两张图有助于理解,如果想调控概率的话直接修改概率数组即可,实战案例:http://t.csdn.cn/P9QKJ 其实在做概率类相关的界面效果的时候,我们真实做法都是在刷新界面前已经把结果获取 ...

  8. 音效管理android,Android之声音管理器《AudioManager》的使用以及音量控制

    以下为网上下载然后拼接-- Android声音管理AudioManager使用 手机都有声音模式,声音.静音还有震动,甚至震动加声音兼备,这些都是手机的基本功能.在Android手机中,我们同样可以通 ...

  9. unity网络实战开发(丛林战争)-正式开发阶段(018-声音管理器模块的完善)

    使用工具:VS2017,unity3d 使用语言:c# 作者:Gemini_xujian 参考:siki老师-<丛林战争>视频教程 上一篇文章中,已经完成了注册事件的处理,接下来将完善声音 ...

最新文章

  1. iOS微博web网页出现的天坑 (斗鱼App 当前版本5.600有这个bug)
  2. VTK:图片之ImageValueRange
  3. PHP秒杀截流原理,流量新大陆:巧借PC、移动端评论截流,让精准流量“爆起来”...
  4. 444 nginx_程序员安全规范:安全无小事,安全防范从nginx配置做起
  5. Atitit.guice3 ioc 最佳实践 o9o
  6. Markdown桌面最佳编辑器
  7. 图论算法真的那么难吗?知识点都在这了……
  8. mysql英文版怎么调中文_navicat for mysql怎么设置中文
  9. 忠实履行职责,热忱完成工作,坚持必胜信念,成就辉煌人生——《西点军校的经典法则》
  10. CodeForces-1062E LCA,DFN,RMQ
  11. HTML5笔记(一)
  12. 苹果开发者账号Apple ID如何进行资料修改?
  13. 在SQL中limit 函数的使用
  14. htb inject
  15. 喜讯!双驰企业正式成为欧盟地平线2020 项目合作伙伴
  16. keil MDK5.24打开MDK5.15及以前STM32工程报错Error #545:Required gpdsc file 'FrameworkCubeMX.gpdsc' is missing
  17. 29 | “懒惰”应该是所有程序员的骄傲
  18. c语言上机试题8,7-8-C语言上机考试试题2.doc
  19. 详细介绍javascript中的单体模式singleton(全面)
  20. 字符串copy函数技术推演

热门文章

  1. 了解一下ARM CPU架构
  2. mmdetection生成测试集的测试结果并保存在.json
  3. 计算机怎么音乐设置,怎样设置音乐一直播放?设置音乐一直播放教程
  4. 如何恢复libselinux.so.1文件 - 教训
  5. 使用pinia持久化插件时踩过的坑
  6. java中的stream基本使用
  7. 物联网架构实例—部标过检工具使用(物联网套件压测)
  8. gadget之composite
  9. 个推推送项目实用(二)
  10. 动漫界的ImageNet来了!人脸数据集AnimeCeleb,240万张图片生成「萌萌哒」动漫脸...