前言

众所周知, Unity自带音效播放没有回调,不能自动播放clip列表; 所以简单实现一个带自动播放功能的接口,用以实现音乐列表的逐个播放.

一. 功能分析

  1. 首先要求切换场景时音乐不停,只在需要时播放
  2. 其次即传入音乐名和播放次数,即可将该音乐循环播放指定次数
  3. 可以直接传入一个包含音乐名和播放次数的列表, 将所有列表中的音乐全部播放指定次数
  • 第一点很好解决,只要将挂载AudioListenerAudioSource的节点设置为切换场景不销毁即可
  • 第二个功能则需要通过开启协程,通过协程来判断音乐的播放状态, 再传入回调函数, 递归调用播放音乐函数
  • 第三个功能在第二个功能的基础上实现,通过传入回调函数并递归实现

二.实现

  1. 初始化
    这里的选择是创建一个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;}
}
  1. 音乐播放
    函数传入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();}
  1. 播放列表
    这里只要利用回调函数来移动下标就可以了
    //播放列表音乐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 简易音乐播放系统相关推荐

  1. 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器

    单片机课程设计简易音乐播放器 论文题目:简易音乐播放器所属系部:电子工程系 指导教师: 学生姓名: 学 号: 专 业: 电子信息工程技术 题目: 简易音乐播放器任务与要求:本设计以 MCS-51 系列 ...

  2. 【毕业设计】28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文)

    typora-root-url: ./ [毕业设计]28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文) 文章目录 typora-root-url: ./ ...

  3. JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)

    JavaScript + Audio API自制简易音乐播放器(详细完整版) ** 音乐播放器的功能清单如下: ** 1.点击暂停按钮,歌曲暂停 2.点击播放按钮,歌曲播放 3.单曲循环与取消单曲循环 ...

  4. 基于SpringBoot的在线音乐播放系统

    项目目录 一.项目概述 二.开发环境 三.系统搭建 四.用户功能 1.注册 2.登录 3.首页 4.歌单 5.歌手 6.收藏 7.搜索 8.播放 五.管理员功能 1.登录 2.系统首页 3.用户管理 ...

  5. html实现简易音乐播放器

    目标: 使用vue.js导包的形式做一个简单的音乐播放器,新手也很容易看懂. 内容: 1. 使用了flex实现响应式布局: 2. 使用min-width防止字体被压缩: 3. 使用computed计算 ...

  6. Android Studio简易音乐播放器设计作业

    Android Studio简易音乐播放器设计作业 实验成功展示 实验代码 MainActivity.java XML文件 class文件 利用BroadcastReceiver模拟音乐播放器,实现播 ...

  7. 毕业设计——音乐播放系统 可以自己上传歌曲 SSM框架 MYSQL数据库 功能齐全

    音乐播放系统 可以自己上传歌曲 SSM框架 MYSQL数据库 功能齐全 可以注册账号 登录 在线上传歌曲 发表评论 在线听音乐 登录 注册 首页 播放音乐以及在线评论 个人后台页面 查看我发布的以及上 ...

  8. Java在线音乐播放系统的设计与实现

    为了使用户可以在网络上在线欣赏音乐并且下载歌曲,方便用户对音乐资源的管理,设计并实现了该时光在线音乐播放系统.本时光在线音乐系统使用了Java web与B/S架构开发.通过实这个时光在线音乐播放系统, ...

  9. 【微信小程序】简易音乐播放器,进度条拖拉、音乐的播放与暂停

    小程序简易音乐播放器实现 粗糙的页面设计: wxml部分: <view class="test"><view class="img">& ...

最新文章

  1. adobe怎么统计字数_本科毕业论文怎么写(正文写作要点精华)
  2. 233网校java_java辅导:使用java模拟登陆考试大
  3. ubuntu 更新软件
  4. 百度定位SDK实现获取当前经纬度及位置
  5. Kuro and Walking Route CodeForces - 979C (树上DFS)
  6. python(matplotlib1)——figure图像,坐标设置
  7. OpenCASCADE:使用扩展数据交换 XDE之几何尺寸和公差 (GDT)
  8. [2021.07.25更新]循环冗余校验(CRC)的MATLAB实现
  9. 交替最小二乘矩阵分解_使用交替最小二乘矩阵分解与pyspark建立推荐系统
  10. 8本前沿技术书,助力这届「青年人」将科幻变成现实
  11. 2014年百度之星程序设计大赛 - 初赛(第二轮)JZP Set
  12. python保存mat文件_python读取文件——python读取和保存mat文件
  13. 搜索接口php,【微信公众平台开发】百度周边搜索接口php封装
  14. android psd预览图软件,来自psd的Android Vector drawable具有空预览
  15. 模拟登录幸运抽奖(java)
  16. 服务器raid发生故障如何恢复数据?- raid5磁盘阵列数据恢复方法
  17. 熟识 : 计算机文化(收藏)
  18. C#开启路由器upnp功能
  19. 第39级台阶(递归+dp)
  20. fantastic website

热门文章

  1. Android 使用uInput模拟手柄设备
  2. 右键在打开方式选择不了绿色版source insight应用程序
  3. 从0.1开始学Python——[17]
  4. 谈谈地图中的道路绘制
  5. Oracle数据库中的包(七)
  6. 湖北省高职高专计算机专业排名,湖北高职高专学校排名
  7. 如果是初学C语言请看完 一些成功人士的心得
  8. (happytime)Onvif Server端口占用 10013问题解决方法
  9. MS project 2007 中将周六周日改为工作日
  10. 美的:100亿,数字化转型路径与实践