Unity 简易音乐播放系统
前言
众所周知, Unity自带音效播放没有回调,不能自动播放clip列表; 所以简单实现一个带自动播放功能的接口,用以实现音乐列表的逐个播放.
一. 功能分析
- 首先要求切换场景时音乐不停,只在需要时播放
- 其次即传入音乐名和播放次数,即可将该音乐循环播放指定次数
- 可以直接传入一个包含音乐名和播放次数的列表, 将所有列表中的音乐全部播放指定次数
- 第一点很好解决,只要将挂载
AudioListener
和AudioSource
的节点设置为切换场景不销毁即可 - 第二个功能则需要通过开启协程,通过协程来判断音乐的播放状态, 再传入回调函数, 递归调用播放音乐函数
- 第三个功能在第二个功能的基础上实现,通过传入回调函数并递归实现
二.实现
- 初始化
这里的选择是创建一个AudioSystem
节点挂在Listener
,下面挂着两个节点分别挂载音乐节点和音效节点.
将父节点设置为不因场景跳转销毁的模式.
注意在这里我将Loop
属性关闭, 因为我是通过音乐是否在播放来实现协程检测的.
public class AudioSystem : MonoBehaviour
{// 单例static AudioSystem audioSys;// 音乐播放static AudioSource musicSource;// 音效播放static AudioSource soundSource;void Awake(){DontDestroyOnLoad(gameObject);}public static AudioSystem Instance{get{if(audioSys == null){audioSys = new GameObject("AudioSystem").AddComponent<AudioSystem>();audioSys.gameObject.AddComponent<AudioListener>();audioSys.Init();}return audioSys;}}void Init(){musicSource = new GameObject("musicSource").AddComponent<AudioSource>();musicSource.transform.SetParent(audioSys.transform);musicSource.playOnAwake = false;musicSource.loop = false;soundSource = new GameObject("soundSource").AddComponent<AudioSource>();soundSource.transform.SetParent(audioSys.transform);soundSource.playOnAwake = false;soundSource.loop = false;}
}
- 音乐播放
函数传入name
音乐名,loopTime
循环次数,action
回调函数
public void PlayMusic(string name, int loopTime, Action action = null)
通过协程实际上很好实现,AudioSource
中有个属性为IsPlaying
,通过这个属性我们可以随时知道当前是否有音频在播放; 所以直接开一个协程等待即可.
- 主要分为几步:
- 判断是否正在播放该音频,如果是,那么重启一个协程即可,
- 如果不是当前正在播放的音频,则加载需要播放的资源并播放.
- 开启协程时,将循环次数减少,代表还剩多少遍播放.
协程中:
- 先等待音乐播放完
- 播完后判断是否需要循环
- 循环的话就调用
PlayMusic
- 不循环则执行回调
static string nowName = null;static Coroutine coroutine;// 播放完成执行acionpublic void PlayMusic(string name, int loopTime, Action action = null){if (coroutine != null)StopCoroutine(coroutine);if(nowName == name){//正在播放当前资源if(!musicSource.isPlaying)musicSource.Play();}else{//加载资源AudioClip clip = Resources.Load<AudioClip>(PATH + fname + ".wav");if(clip == null)return;if (musicSource.isPlaying)musicSource.Stop();musicSource.clip = clip;nowName = name;musicSource.Play();}// 开启协程,并将循环次数 - 1coroutine = StartCoroutine(MusicLoop(name, loopTime - 1, action));}IEnumerator MusicLoop(string path, int loopTime, Action action = null){//等待播放完毕while (musicSource.isPlaying) yield return null;//播放次数不为0就继续循环if (loopTime != 0)PlayMusic(path, loopTime, action);//播放完毕且有回调则执行else if(action != null)action();}
- 播放列表
这里只要利用回调函数来移动下标就可以了
//播放列表音乐public void PlayMusicList(List<KeyValuePair<string, int>> list, int index = 0){if (list == null || index >= list.Count) return;PlayMusic(list[index].Key, list[index].Value, () =>{PlayMusicList(list, index + 1);});}
三. 完整代码
- 注意销毁协程
public class AudioSystem : MonoBehaviour
{// 单例static AudioSystem audioSys;// 音乐播放static AudioSource musicSource;// 音效播放static AudioSource soundSource;// 当前音乐名static string nowName = null;void Awake(){DontDestroyOnLoad(gameObject);}// 单例public static AudioSystem Instance{get{if(audioSys == null){audioSys = new GameObject("AudioSystem").AddComponent<AudioSystem>();audioSys.gameObject.AddComponent<AudioListener>();audioSys.Init();}return audioSys;}}// 创建两个子节点void Init(){musicSource = new GameObject("musicSource").AddComponent<AudioSource>();musicSource.transform.SetParent(audioSys.transform);musicSource.playOnAwake = false;musicSource.loop = false;soundSource = new GameObject("soundSource").AddComponent<AudioSource>();soundSource.transform.SetParent(audioSys.transform);soundSource.playOnAwake = false;soundSource.loop = false;}//播放列表音乐public void PlayMusicList(List<KeyValuePair<string, int>> list, int index = 0){if (list == null || index >= list.Count) return;PlayMusic(list[index].Key, list[index].Value, () =>{PlayMusicList(list, index + 1);});}static Coroutine coroutine;// 播放完成执行acionpublic void PlayMusic(string name, int loopTime, Action action = null){if (coroutine != null)StopCoroutine(coroutine);if(nowName == name){//正在播放当前资源if(!musicSource.isPlaying)musicSource.Play();}else{//加载资源AudioClip clip = Resources.Load<AudioClip>(PATH + fname + ".wav");if(clip == null)return;if (musicSource.isPlaying)musicSource.Stop();musicSource.clip = clip;nowName = name;musicSource.Play();}// 开启协程,并将循环次数 - 1coroutine = StartCoroutine(MusicLoop(name, loopTime - 1, action));}IEnumerator MusicLoop(string path, int loopTime, Action action = null){//等待播放完毕while (musicSource.isPlaying) yield return null;//播放次数不为0就继续循环if (loopTime != 0)PlayMusic(path, loopTime, action);//播放完毕且有回调则执行else if(action != null)action();}public void SetMusicVolume(float volume){musicSource.volume = Mathf.Clamp(volume, 0, 1);}public void PlayOneShot(string name){}private void OnDestroy(){if (coroutine != null)StopCoroutine(coroutine);}
}
Unity 简易音乐播放系统相关推荐
- 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器
单片机课程设计简易音乐播放器 论文题目:简易音乐播放器所属系部:电子工程系 指导教师: 学生姓名: 学 号: 专 业: 电子信息工程技术 题目: 简易音乐播放器任务与要求:本设计以 MCS-51 系列 ...
- 【毕业设计】28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文)
typora-root-url: ./ [毕业设计]28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文) 文章目录 typora-root-url: ./ ...
- JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)
JavaScript + Audio API自制简易音乐播放器(详细完整版) ** 音乐播放器的功能清单如下: ** 1.点击暂停按钮,歌曲暂停 2.点击播放按钮,歌曲播放 3.单曲循环与取消单曲循环 ...
- 基于SpringBoot的在线音乐播放系统
项目目录 一.项目概述 二.开发环境 三.系统搭建 四.用户功能 1.注册 2.登录 3.首页 4.歌单 5.歌手 6.收藏 7.搜索 8.播放 五.管理员功能 1.登录 2.系统首页 3.用户管理 ...
- html实现简易音乐播放器
目标: 使用vue.js导包的形式做一个简单的音乐播放器,新手也很容易看懂. 内容: 1. 使用了flex实现响应式布局: 2. 使用min-width防止字体被压缩: 3. 使用computed计算 ...
- Android Studio简易音乐播放器设计作业
Android Studio简易音乐播放器设计作业 实验成功展示 实验代码 MainActivity.java XML文件 class文件 利用BroadcastReceiver模拟音乐播放器,实现播 ...
- 毕业设计——音乐播放系统 可以自己上传歌曲 SSM框架 MYSQL数据库 功能齐全
音乐播放系统 可以自己上传歌曲 SSM框架 MYSQL数据库 功能齐全 可以注册账号 登录 在线上传歌曲 发表评论 在线听音乐 登录 注册 首页 播放音乐以及在线评论 个人后台页面 查看我发布的以及上 ...
- Java在线音乐播放系统的设计与实现
为了使用户可以在网络上在线欣赏音乐并且下载歌曲,方便用户对音乐资源的管理,设计并实现了该时光在线音乐播放系统.本时光在线音乐系统使用了Java web与B/S架构开发.通过实这个时光在线音乐播放系统, ...
- 【微信小程序】简易音乐播放器,进度条拖拉、音乐的播放与暂停
小程序简易音乐播放器实现 粗糙的页面设计: wxml部分: <view class="test"><view class="img">& ...
最新文章
- adobe怎么统计字数_本科毕业论文怎么写(正文写作要点精华)
- 233网校java_java辅导:使用java模拟登陆考试大
- ubuntu 更新软件
- 百度定位SDK实现获取当前经纬度及位置
- Kuro and Walking Route CodeForces - 979C (树上DFS)
- python(matplotlib1)——figure图像,坐标设置
- OpenCASCADE:使用扩展数据交换 XDE之几何尺寸和公差 (GDT)
- [2021.07.25更新]循环冗余校验(CRC)的MATLAB实现
- 交替最小二乘矩阵分解_使用交替最小二乘矩阵分解与pyspark建立推荐系统
- 8本前沿技术书,助力这届「青年人」将科幻变成现实
- 2014年百度之星程序设计大赛 - 初赛(第二轮)JZP Set
- python保存mat文件_python读取文件——python读取和保存mat文件
- 搜索接口php,【微信公众平台开发】百度周边搜索接口php封装
- android psd预览图软件,来自psd的Android Vector drawable具有空预览
- 模拟登录幸运抽奖(java)
- 服务器raid发生故障如何恢复数据?- raid5磁盘阵列数据恢复方法
- 熟识 : 计算机文化(收藏)
- C#开启路由器upnp功能
- 第39级台阶(递归+dp)
- fantastic website