当前位置: 首页 > news >正文

Unity——音频管理器(附例子)

在实际游戏开发中,音效既是一个相对独立的部分,又与其他游戏逻辑密切关联。也就是说,与音效相关的代码会插入很多细节代码中。

而且在音效非常丰富的情况下,如果每一个游戏模块都单独播放音效,那么可能会带来一些问题。例如,Audio Source组件很多,但大部分限制,同时播放的音效太多会显得混乱。

成熟的技术开发思路是:如果音效不多、没有造成问题,则完全可以简单处理;如果音效已经引起了代码的混乱和性能问题,就有必要统一管理所有的音源和音效,也就是设计一个易用的音频管理器。有了音频管理器,所有的Audio Source组件都会统一创建,而所有音效播放的需求都要通过调用音频管理器的方法简介实现。

音频管理器有很多设计思路,其中一种比较简洁的思路是,事先指定游戏中最多同时播放多少个音频,然后创建若干个音源。例如,最多播放8个音频,那么就创建8个Audio Source组件,这8个组件可以看作8个频道。需要播放音频时,只要找到任意一个空闲的频道播放即可;而如果8个频道都正在播放,那么就可以用某种策略替换音频(如将播放时间最早的音频替换成新的音频)。用这种简单的思路创建音频管理器的代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//音频管理器
public class AudioManager : MonoBehaviour
{// 整个游戏中,总的音源数量private const int AUDIO_CHANNEL_NUM = 8;private struct CHANNEL{public AudioSource channel;public float keyOnTime; //记录最近一次播放音乐的时刻};private CHANNEL[] m_channels;void Awake(){m_channels = new CHANNEL[AUDIO_CHANNEL_NUM];for (int i = 0; i < AUDIO_CHANNEL_NUM; i++){//每个频道对应一个音源m_channels[i].channel = gameObject.AddComponent<AudioSource>();m_channels[i].keyOnTime = 0;}}//公开方法:播放一次,参数为音频片段、音量、左右声道、速度//这个方法主要用于音效,因此考虑了音效顶替的逻辑public int PlayOneShot(AudioClip clip, float volume, float pan, float pitch = 1.0f){for (int i = 0; i < m_channels.Length; i++){//如果正在播放同一个片段,而且刚刚才开始,则直接退出函数if (m_channels[i].channel.isPlaying &&m_channels[i].channel.clip == clip &&m_channels[i].keyOnTime >= Time.time - 0.03f)return -1;}//遍历所有频道,如果有频道空闲直接播放新音频,并退出//如果没有空闲频道,先找到最开始播放的频道(oldest),稍后使用int oldest = -1;float time = 10000000.0f;for (int i = 0; i < m_channels.Length; i++){if (m_channels[i].channel.loop==false &&m_channels[i].channel.isPlaying  &&m_channels[i].keyOnTime < time){oldest = i;time=m_channels[i].keyOnTime;}if (!m_channels[i].channel.isPlaying){m_channels[i].channel.clip=clip;m_channels[i].channel.volume=volume;m_channels[i].channel.pitch=pitch;m_channels[i].channel.panStereo=pan;m_channels[i].channel.loop = false;m_channels[i].channel.Play();m_channels[i].keyOnTime = Time.time;return i;}}//运行到这里说明没有空闲频道。让新的音频顶替最早播出的音频if(oldest>=0){m_channels[oldest].channel.clip = clip;m_channels[oldest].channel.volume = volume;m_channels[oldest].channel.pitch = pitch;m_channels[oldest].channel.panStereo = pan;m_channels[oldest].channel.loop = false;m_channels[oldest].channel.Play();m_channels[oldest].keyOnTime = Time.time;return oldest;}return -1;}//公开方法:循环播放,用于播放长时间的背景音乐,处理方式相对简单一些public int PlayLoop(AudioClip clip, float volume, float pan, float pitch = 1.0f){for(int i = 0; i < m_channels.Length; i++){if (!m_channels[i].channel.isPlaying){m_channels[i].channel.clip = clip;m_channels[i].channel.volume = volume;m_channels[i].channel.pitch = pitch;m_channels[i].channel.panStereo = pan;m_channels[i].channel.loop = true;m_channels[i].channel.Play();m_channels[i].keyOnTime = Time.time;return i;}}return -1;}//公开方法:停止所有音频public void StopAll(){foreach(CHANNEL channel in m_channels)channel.channel.Stop();}//公开方法:根据频道ID停止音频public void Stop(int id){if (id>= 0&& id < m_channels.Length){m_channels[id].channel.Stop();}}
}

以上代码可以作为创建音频管理器的一种思路参考。

实际上,根据游戏类型的不同,音频管理器的创建思路也有区别。例如,在很多3D游戏中,需要考虑音效播放的空间位置(目的是营造真实感),这是统一创建音源就不是很合适了

http://www.lryc.cn/news/148377.html

相关文章:

  • TCP协议基础
  • C# NetTopologySuite+ProjNet 任意图形类型坐标转换
  • Windows笔记本电脑开机黑屏
  • Samb共享用户的设置和修改Linux用户的id号,修改Linux组的id号,加入组,删除组成员等
  • VBA:对Excel单元格进行合并操作
  • HTML5离线储存
  • cmd: Union[List[str], str], ^ SyntaxError: invalid syntax
  • 2023高教社杯数学建模思路 - 案例:异常检测
  • FFDNet-pytorch版本代码测试教程
  • uni-app项目由hbuilder项目转化为cli项目
  • 使用SpaceDesk连接平板作为电脑副屏详细步骤教程
  • 云备份——第三方库使用介绍(下)
  • springboot实战(一)之项目搭建
  • 线性代数的学习和整理16:什么是各种空间(类型),向量空间,距离(类型)?
  • css实现文字翻转效果
  • 19 Linux之Python定制篇-apt软件管理和远程登录
  • WebDAV之π-Disk派盘 + notototo
  • _kbhit() and getch() 在小游戏中用不了。因为控制台函数,仅在控制台程序中可用
  • dayjs格式转换成日期
  • mfc140u.dll丢失如何修复?解析mfc140u.dll是什么文件跟修复方法分享
  • STM32--SPI通信与W25Q64(2)
  • 微信小程序 校园周边美食商城分享系统
  • K8S - 架构、常用K8S命令、yaml资源清单部署、Ingress、故障排查、存储卷
  • micro benchmark 使用经验
  • nodejs发布静态https服务器
  • 国产系统下开发QT程序总结
  • 【Redis】redis入门+java操作redis
  • 无涯教程-Android - Spinner函数
  • 国标GB28181视频平台EasyGBS国标平台智能边缘计算网关关于小区电动车进电梯的应用方案设计
  • supervisorctl(-jar)启动配置设置NACOS不同命名空间