音乐播放器的实现(四) 您所在的位置:网站首页 qq音乐怎么才可以按顺序播放 音乐播放器的实现(四)

音乐播放器的实现(四)

2024-06-08 15:25| 来源: 网络整理| 查看: 265

音乐播放器的实现(四)—— 歌曲列表、顺序播放、单曲循环、随机播放、自动下一曲

传送门:(完整工程见第五章篇尾) 音乐播放器的实现(一)—— Audio Listener和Audio Source面板的介绍 音乐播放器的实现(二)—— UI面板的制作 音乐播放器的实现(三)—— 进度条控制、播放、暂停、上(下)一曲、播放时间和总时间显示 音乐播放器的实现(五)—— 音量的加减和静音 前言: 上一篇简单的实现了算是顺序播放的上一曲和下一曲,这篇加上播放模式(顺序播放、单曲循环、随机播放),再优化上/下一曲,同时显示所有歌曲的列表,并能点击播放对应的歌曲音频。

先看下最终效果: 在这里插入图片描述 具体操作 一、首先,我们还是先完善UI面板: 1、在上一篇的基础上,新建一个按钮Button命名为pModeImage,Button的图片用来显示播放模式对应的图片(文本可以删掉); 2、准备三张图片放入Project面板中的Resources文件夹下的Sprite文件夹中(可根据自己需求放置,但一定要在Resources文件夹下,当然后台代码对应的路径也要更改),分别命名为:stright、circle和random; 3、新建一个Scroll View,用来显示歌曲的列表,在content下新建一个Button,用来点击播放对应歌曲。在content上添加布局组件,调整相关参数,使Button大小位置合适,最后把该Button拖至Project面板中形成一个预制体,存放在Prefab文件夹中,再删掉或隐藏掉content下的Button按钮。 最终效果如下图所示: 在这里插入图片描述 二、核心代码 1、相对上一篇,我把播放音频的方法独立了出来,方便调用。

/// /// 播放索引为index的音频 /// /// 音频索引 void playMusic(int index) { aus.clip = auc[index]; //音频播放器的音频为aus数组中索引对应的音频 slid.value = 0; //初始化进度条 aus.time = 0; //初始化音乐的播放时间(从头开始播) aus.Play(); //播放音频 }

2、音乐列表 实例化每个音频按钮,形成音乐列表,该方法在Start()中调用,即开始运行时就形成歌曲列表。(其中 item为上面制作的Button预制体。) 在这里插入图片描述在这里插入图片描述

public GameObject item; //要实例化的列表按钮对象,即Button预制体 private GameObject it; //实例化出的列表音频按钮 void initItem()//音频列表 { List L = new List();//列表L for (int i = 0; i gob.GetComponent().onClick.AddListener(delegate { index = Array.IndexOf(g, gob); //获取当前点击的按钮在数组g中的索引 playMusic(index); //播放音频 }); } }

效果如下图所示: 在这里插入图片描述 3、播放模式 (1)枚举出顺序播放、单曲循环、随机播放这三个模式:

public enum playMode { stright,//列表循环 circle1,//单曲循环 random //随机播放 } private playMode playM = playMode.stright; //初始是顺序播放 private GameObject pModeImage; //播放模式的图片切换

在Start()中调用:

void initPlayMode()//初始化播放模式 { //找到名为pModeImage的按钮 pModeImage = GameObject.Find("pModeImage"); //给它添加监听(调用PlayMode方法,来切换播放模式) pModeImage.GetComponent().onClick.AddListener(PlayMode); }

以下为PlayMode()方法:

//变量t,初始值为1 int t = 1; /// /// 播放模式 /// public void PlayMode() { t++; if (t == 1) { //播放模式为顺序播放 playM = playMode.stright; //上传顺序播放对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/stright"); } if(t==2) { //播放模式为单曲循环 playM = playMode.circle1; //上传单曲循环对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/circle"); } if(t==3) { //播放模式为随机播放 playM = playMode.random; //上传速记播放对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/random"); //初始化t t = 0; } }

(2)重新修改了LastMusic()和NextMusic()方法: 上一曲:

private void LastMusic() { if (playM == playMode.random) //如果播放模式是随机播放 randomRange(); //随机播放 else { index--; //索引减一 //若索引等于-1,即当前播放的音频是aus数组列表的第一首,则上一首应为aus数组列表的最后一首 if (index == -1) index = auc.Length - 1; playMusic(index); } }

下一曲:

private void NextMusic() { if(playM==playMode.random) //如果播放模式是随机播放 randomRange(); //随机播放 else { index++; //索引加一 //若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首 if (index == auc.Length) index = 0; playMusic(index);//播放音频 } }

随机播放时调用的代码:

public void randomRange()//随机播放 { int r = UnityEngine.Random.Range(0, auc.Length);//生成随机数(包含0,不包含auc.Length); if(index == r) //如果随机数等于当前播放的音频的索引(避免播放同一首) r++; //索引加一 //若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首 if (r == auc.Length) r = 0; playMusic(r);//播放音频 }

4、自动播放下一曲 当进度条走到最后时,播放下一曲,若是单曲循环,则依旧播放当前的音频

void Slider()//当进度条走到最后时,播放下一曲 { if (currentHour == clipHour && currentMinute == clipMinute && currentSecond == clipSecond) { if (playM == playMode.circle1)//如果播放模式是单曲循环,下一曲还是当前这首 playMusic(index); else NextMusic();//下一曲 } } 完整版代码:

DragSlider脚本不变。 Player脚本如下:

using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Player: MonoBehaviour { public enum playMode { stright,//列表循环 circle1,//单曲循环 random //随机播放 } public Text musicName; //显示歌曲的名字及歌手 public Text nowTime; //显示歌曲已播放的时间长度 public Text allTime; //显示当前歌曲的总时间长度 public Slider slid; //进度条 public Transform buttons; //按钮所在的集合体 public AudioClip[] auc; //存放歌曲的数组 public AudioSource aus; //音频播放器 private int index; //数组aus的索引 private int currentHour, currentMinute, currentSecond; //已播放的时间(时、分、秒) private int clipHour, clipMinute, clipSecond; //总时间(时、分、秒) private playMode playM=playMode.stright; //初始是顺序播放 private GameObject pModeImage; //播放模式的图片切换 private GameObject vioce_butt, voice_text, voice_slid; //音量按钮、音量数字、音量进度条 int clickNum=0,value;//变量 bool mouseIn;//鼠标进入 public GameObject item; //要实例化的列表按钮对象 private GameObject it; //实例化出的列表音频按钮 public static Player _instance; void initItem()//音频列表 { List L = new List();//列表L for (int i = 0; i gob.GetComponent().onClick.AddListener(delegate { index = Array.IndexOf(g, gob); playMusic(index); //播放音频 }); } } void initVoice()//初始化 { vioce_butt = GameObject.Find("voice_button"); voice_text = GameObject.Find("voice_text"); voice_slid = GameObject.Find("voice_slider"); //voice_slid.SetActive(false); //开始时声音进度条不显示(当鼠标放在音量按钮上时显示) voice_slid.GetComponent().value = 20;//开始声音为20; //开始先调用一次,设置初始的音量大小 voice(); //给进度条添加监听,进度条的值改变即调用voice()方法 voice_slid.GetComponent().onValueChanged.AddListener(delegate { voice(); }); //给声音按钮添加监听 vioce_butt.GetComponent().onClick.AddListener(delegate { clickNum++;//点击按钮的次数 if(clickNum==1)//1为打开静音,0为关闭静音 { //打开音频播放器的静音 aus.mute = true; //上传对应的静音的图片 vioce_butt.GetComponent().sprite = Resources.Load("Sprite/voiceMute"); //存下点击静音时的进度条的值 value = (int)voice_slid.GetComponent().value; //进度条的value值为0 voice_slid.GetComponent().value = 0; } else { //关闭音频播放器的静音 aus.mute = false; //上传对应的不静音的图片 vioce_butt.GetComponent().sprite = Resources.Load("Sprite/voice1"); //进度条的值变为关闭静音前的值 voice_slid.GetComponent().value = value; //初始化点击次数 clickNum = 0; } }); } void initPlayMode()//初始化播放模式 { //找到名为pModeImage的按钮 pModeImage = GameObject.Find("pModeImage"); //给它添加监听(调用PlayMode方法,来切换播放模式) pModeImage.GetComponent().onClick.AddListener(PlayMode); } void Start() { _instance = this; aus.Stop(); //开始运行时不播放,点播放键才开始播放 #region 注:该方式虽然可以直接达到拖动进度条就播放到进度条当前的音乐,但会产生滋滋啦啦的杂音,是因为进度条value变化,使之不断调用onValueChanged,从而让音乐的进度发生了变化,音乐前后颠倒,不断重叠 /// /// 所以新建了个DragSlider脚本,挂在进度条上,来实现拖动播放的效果 /// //slid.onValueChanged.AddListener(delegate //{ // //加上之后,避免拖动进度条到最后不松手时报错 // if (slid.value == 1) // return; // //给进度条添加事件监听,每当拖动进度条,歌曲从相应的位置播放 // aus.time = slid.value * aus.clip.length; //}); #endregion foreach (Transform go in buttons) //遍历所有的操作按钮 { go.GetComponent().onClick.AddListener(delegate //根据按钮名给按钮添加事件监听 { switch (go.name) { case "lastM": //点击“上一曲”按钮 LastMusic(); break; case "pause": //点击“暂停”按钮 Pause(); break; case "play": //点击“播放”按钮 Play(); break; case "nextM": //点击“下一曲”按钮 NextMusic(); break; } }); } initItem(); //音频列表 initVoice(); //音量部分初始化 initPlayMode(); //初始化播放模式 } void Update () { //当前播放过的时间 nowtime(); //当前正在播放的音频的总时间 alltime(); //当前正在播放的音乐 nowMusic(); //单机左键,隐藏所有要隐藏的 //setActiveFalse(); } void nowtime()//当前播放过的时间 { currentHour = (int)aus.time / 3600; //时 currentMinute = (int)(aus.time - currentHour * 3600) / 60;//分 currentSecond = (int)(aus.time - currentHour * 3600 - currentMinute * 60);//秒 //显示当前播放过的时间 nowTime.text = string.Format("{0:D2}:{1:D2}:{2:D2} ", currentHour, currentMinute, currentSecond); //进度条变化 //(之后更新版)如果当前没有拖拽进度条 if(!DragSlider.isDrag) slid.value = aus.time / aus.clip.length; } /// /// 歌曲总时间 /// void alltime() { //slid.value = 0; clipHour = (int)aus.clip.length / 3600;//时 clipMinute = (int)(aus.clip.length - clipHour * 3600) / 60;//分 clipSecond = (int)(aus.clip.length - clipHour * 3600 - clipMinute * 60);//秒 //显示歌曲总时间 allTime.text = string.Format("{0:D2}:{1:D2}:{2:D2}", clipHour, clipMinute, clipSecond); } /// /// 上一曲 /// private void LastMusic() { if (playM == playMode.random) //如果播放模式是随机播放 randomRange(); //随机播放 else { index--; //索引减一 //若索引等于-1,即当前播放的音频是aus数组列表的第一首,则上一首应为aus数组列表的最后一首 if (index == -1) index = auc.Length - 1; playMusic(index); } } private void Pause() //暂停 { aus.Pause(); } private void Play() //播放 { //如果当前正在播放,则返回 if (aus.isPlaying) return; aus.Play(); } /// /// 下一曲 /// public void NextMusic() { if(playM==playMode.random) //如果播放模式是随机播放 randomRange(); //随机播放 else { index++; //索引加一 //若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首 if (index == auc.Length) index = 0; playMusic(index);//播放音频 } } void nowMusic() //当前的音频 { AudioClip clip = aus.clip; //当前播放的音频 string n = aus.clip.name; //当前播放的音频的名字 string[] na = n.Split('-'); //以“-”为分割点,把音频名分为若干部分 //显示当前正在播放的歌曲的名字【歌曲名(默认字体,25号)+歌手名(默认字体,18号,红色)的形式】 musicName.text = string.Format("{0}" + "\n{1}", na[0], na[1]); index = Array.IndexOf(auc, clip);//当前播放的音频在aus数组中的索引 Slider(); //当进度条走到最后时,播放下一曲 } void Slider()//当进度条走到最后时,播放下一曲 { if (currentHour == clipHour && currentMinute == clipMinute && currentSecond == clipSecond) { if (playM == playMode.circle1)//如果播放模式是单曲循环,下一曲还是当前这首 playMusic(index); else NextMusic();//下一曲 } } /// /// 播放索引为index的音频 /// /// 音频索引 void playMusic(int index) { aus.clip = auc[index]; //音频播放器的音频为aus数组中索引对应的音频 slid.value = 0; //初始化进度条 aus.time = 0; //初始化音乐的播放时间(从头开始播) aus.Play(); //播放音频 } //变量t int t = 1; /// /// 播放模式 /// public void PlayMode() { t++; if (t == 1) { //播放模式为顺序播放 playM = playMode.stright; //上传顺序播放对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/stright"); } if(t==2) { //播放模式为单曲循环 playM = playMode.circle1; //上传单曲循环对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/circle"); } if(t==3) { //播放模式为随机播放 playM = playMode.random; //上传速记播放对应的图片 pModeImage.GetComponent().sprite = Resources.Load("Sprite/random"); //初始化t t = 0; } } //设置和显示音量大小 void voice() { //把进度条最大值改为100,最小值为0 //音频播放器的音量volume = 进度条的值 * 0.01f。(因为volume的范围为:0~1) aus.volume = voice_slid.GetComponent().value * 0.01f; //音量的文本显示(为进度条的value值,value值是浮点型,这里显示成整型) voice_text.GetComponent().text = ((int)voice_slid.GetComponent().value).ToString(); } public void voice_button(bool on) { if(on) { voice_slid.SetActive(true); mouseIn = true; } else { mouseIn = false; voice_slid.SetActive(false); } } /// /// 单机左键,隐藏所有要隐藏的 /// void setActiveFalse() { if(Input.GetMouseButtonDown(0)) { if(mouseIn==false) voice_slid.SetActive(false); } } public void randomRange()//随机播放 { int r = UnityEngine.Random.Range(0, auc.Length);//生成随机数(包含0,不包含auc.Length); if(index == r) //如果随机数等于当前播放的音频的索引(避免播放同一首) r++; //索引加一 //若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首 if (r == auc.Length) r = 0; playMusic(r);//播放音频 } }

代码备注的也比较详细,若文中存在错误或者描述不清的地方也请指正,欢迎评论区留言共同探讨,以上。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有