⾳乐播放器的实现(四)——歌曲列表顺序播放、单曲循环、随机播放、⾃动
下⼀曲
⾳乐播放器的实现(四)—— 歌曲列表、顺序播放、单曲循环、随机播放、⾃动下⼀曲
传送门:(完整⼯程见第五章篇尾)
前⾔:
上⼀篇简单的实现了算是顺序播放的上⼀曲和下⼀曲,这篇加上播放模式(顺序播放、单曲循环、随机播放),再优化上/下⼀曲,同时显⽰所有歌曲的列表,并能点击播放对应的歌曲⾳频。
先看下最终效果:
具体操作
⼀、⾸先,我们还是先完善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、相对上⼀篇,我把播放⾳频的⽅法独⽴了出来,⽅便调⽤。
/// <summary>
/// 播放索引为index的⾳频
/// </summary>
/// <param name="index">⾳频索引</param>
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<GameObject> L =new List<GameObject>();//列表L
for(int i =0; i < auc.Length; i++)
{
it =Instantiate(item);//实例化⾳频列表的各个按钮
//设置⽗节点为Scroll View下的content
李维嘉女朋友it.transform.SetParent(GameObject.Find("Content").transform,false);
//⾳频名低等动物国语歌词
string[] name = auc[i].name.Split('-');
//连接⾳频名,序号、名字、作者
//把每个按钮放⼊列表L
L.Add(it);
}
GameObject[] g =new GameObject[L.Count];//数组g,长度等于列表L 的长度
L.CopyTo(g);//把列表L的内容复制到数组g中
//给每个⾳频按钮加上监听,点击即播放对应⾳频
foreach(GameObject gob in g)
{
gob.GetComponent<Button>().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<Button>().onClick.AddListener(PlayMode);
}
以下为PlayMode()⽅法:
//变量t,初始值为1
int t =1;
/// <summary>
/// 播放模式
/// </summary>
public void PlayMode()
{
t++;
if(t ==1)
{
//播放模式为顺序播放
playM = playMode.stright;
moutain top//上传顺序播放对应的图⽚
pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/stright");
}
if(t==2)
{
//播放模式为单曲循环
playM = playMode.circle1;
//上传单曲循环对应的图⽚
pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/circle");
}
if(t==3)
{
//播放模式为随机播放
演员王东照片playM = playMode.random;
//上传速记播放对应的图⽚
pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("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 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<GameObject> L =new List<GameObject>();//列表L
for(int i =0; i < auc.Length; i++)
{
it =Instantiate(item);//实例化⾳频列表的各个按钮
//⾳频名
string[] name = auc[i].name.Split('-');
//连接⾳频名,序号、名字、作者
//把每个按钮放⼊列表L
L.Add(it);
}
GameObject[] g =new GameObject[L.Count];//数组g,长度等于列表L 的长度
L.CopyTo(g);//把列表L的内容复制到数组g中
//给每个⾳频按钮加上监听,点击即播放对应⾳频
foreach(GameObject gob in g)
{
gob.GetComponent<Button>().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<Slider>().value=20;//开始声⾳为20;
//开始先调⽤⼀次,设置初始的⾳量⼤⼩
voice();
//给进度条添加监听,进度条的值改变即调⽤voice()⽅法
voice_slid.GetComponent<Slider>().onValueChanged.AddListener(delegate{voice();});
/
/给声⾳按钮添加监听
vioce_butt.GetComponent<Button>().onClick.AddListener(delegate
{
clickNum++;//点击按钮的次数
if(clickNum==1)//1为打开静⾳,0为关闭静⾳
{
//打开⾳频播放器的静⾳
aus.mute =true;
//上传对应的静⾳的图⽚
vioce_butt.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/voiceMute");