Unity开发——音乐播放器的完整搭建过程

        最近在自己的项目开发过程中,Unity3D场景中开发了一个完整的音乐播放器,涉及到歌曲的切换、UI的变化等,虽然看起来都是些简单的代码,但整体的实现逻辑较为复杂,我自己从零开始独自开发,经过了好几次的优化和完善,才得到了比较好的播放器版本。下面我依次介绍一下我的音乐播放器搭建过程。

1 界面GameObject和UI组成介绍

        在搭建过程中,涉及到比较多的还是UI,在UI上,我是通过PS进行一个一个分离开来的,然后再在Unity上进行组装拼接。因为涉及到每个按钮的变化与控制,因此将它们割离开来制作成单独的GameObject进行挂载会使得控制起来方便很多。

2 开发搭建思路

2.1 面板上的歌曲选择

2.1.1 GameObject的设置

        开发时,我最开始实现的便是手柄指到对应的歌曲区域便播放对应的歌曲。这个实现起来也很容易,只要在每个文字区域挂载到Button,然后是Button的大小刚好覆盖到文字区域即可。而因为要显示歌曲文字,因此Button的Image要直接设置为None。具体如下。

2.1.2 Button按钮功能的开发

        在添加好每个Button之后,接下来要实现的便是每个按钮所执行的功能,再将其挂载到Button组件下的On Click下,从而实现手柄点击控制。以下为按钮的控制代码和Unity中显示的面板。

using UnityEngine;
using UnityEngine.UI;

/* 
 * 此代码块用于设计音乐室面板块中音乐的选择功能,同时包括音乐的名字读取、描述展现功能
 * 此代码块中建立了音乐的输出是在unity面板中拉取挂载输入,因此相关的音频文件需提前下载
 * 音乐的描述需手动填写
 * 当前页面一页只呈现8首歌,因此只有8个按钮
 * 后续歌曲超过8首时可以通过控制musicIndex的变化来控制页面选择的音乐
 */

/// <summary>
/// 此代码块用于设计音乐室面板块中音乐的选择功能
/// </summary>

public class MusicContoller : MonoBehaviour
{
    public AudioClip[] musicList; //建立一个数组,用于储存需要播放的音乐
    public GameObject[] SongTitle; //建立一个数组,用于储存歌曲名称的文本物体
    public int musicAmount; //记录音乐的数量
    [SerializeField] GameObject pauseButton; //左下角的暂停按钮
    [SerializeField] GameObject playButton; //左下角的播放按钮
    public int musicIndex; //定位当前播放的音乐,用于后面的上一首和下一首按钮是使用
    public bool isStartMusicPlay = false; //判断是否已经开始播放了音乐,点击任意一首歌后开始变为true

    // Start is called before the first frame update
    void Start()
    {
        AudioSource music = this.GetComponent<AudioSource>();
        musicAmount = musicList.Length; //获取歌曲的数目
        //Debug.Log(musicList[0].name);
        //设置面板的名字输入
        for(int i = 0; i < musicAmount; i++)
        {
            Text songTitle = SongTitle[i].GetComponent<Text>();
            songTitle.text = musicList[i].name;
        }
    }

    /// <summary>
    /// 以下为定义点击每个按钮所播放的音乐已经处理的功能
    ///目前找不到可以识别点击按钮的功能,所以只能一个按钮设置一个功能
    /// </summary>
    public void Button_1_MP()//点击按钮1时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[0];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 0;
        isStartMusicPlay = true;
    }

    public void Button_2_MP()//点击按钮2时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[1];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 1;
        isStartMusicPlay = true;
    }

    public void Button_3_MP()//点击按钮3时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[2];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 2;
        isStartMusicPlay = true;
    }

    public void Button_4_MP()//点击按钮4时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[3];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 3;
        isStartMusicPlay = true;
    }

    public void Button_5_MP()//点击按钮5时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[4];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 4;
        isStartMusicPlay = true;
    }

    public void Button_6_MP()//点击按钮6时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[5];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 5;
        isStartMusicPlay = true;
    }
    public void Button_7_MP()//点击按钮7时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[6];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 6;
        isStartMusicPlay = true;
    }

    public void Button_8_MP()//点击按钮8时播放的音乐
    {
        //设置音乐的播放
        AudioSource music = this.GetComponent<AudioSource>();
        //Debug.Log(0);
        music.clip = musicList[7];
        music.time = 0;
        music.Play();

        //设置选择音乐后左下角按钮的变化
        pauseButton.SetActive(false);
        playButton.SetActive(true);

        musicIndex = 7;
        isStartMusicPlay = true;
    }


}

        在开发完每个按钮的功能之后,接下来的便是把他们依次的挂载到对应的Button组件上。如下如所示。

2.2 面板上的按钮控制

        面板上的按钮控制包括上一首、下一首、播放和暂停、音量控制几个按钮。

2.2.1 GameObject的设置

        这些GameObject对应播放器下面的控制按钮,它们都挂载有Button组件,从而实现手柄的点击控制。

2.2.2 控制按钮的开发代码

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 此代码块用于设计音乐室面板块左下角的上一首、下一首、播放和暂停四个按键的功能
/// </summary>

public class ControllerButton : MonoBehaviour
{
    [SerializeField] private GameObject pauseButton;
    [SerializeField] private GameObject playButton;
    [SerializeField] private GameObject audioController;
    [SerializeField] private GameObject volumeSlider;
    public bool isdisplayVolumeSlider = true; //用于判断是否点击了音量键
    public bool isMusicPause = false; //用于判断音乐是否处于被用户暂停状态,默认为真

    /// <summary>
    /// 定义点击播放按钮的功能
    /// </summary>
    public void PlayButtonController()   
    {
        //播放按钮点击后是为暂停音乐播放
        pauseButton.SetActive(true);
        playButton.SetActive(false);
        AudioSource music = audioController.GetComponent<AudioSource>();
        music.Pause();

        isMusicPause = true; //判断值变为真
    }

    /// <summary>
    /// 定义点击暂停按钮功能
    /// </summary>
    public void PauseButtonController() 
    {
        //暂停按钮点击后是为继续播放音乐功能
        pauseButton.SetActive(false);
        playButton.SetActive(true);
        AudioSource music = audioController.GetComponent<AudioSource>();
        music.Play();

        isMusicPause = false; //点击暂停后判断值变为假
    }

    /// <summary>
    /// 定义下一首按钮的功能
    /// </summary>
    public void ForWardButtonController()
    {
        MusicContoller ac_mc = audioController.GetComponent<MusicContoller>();
        if(ac_mc.musicIndex < ac_mc.musicAmount-1)
        {
            ac_mc.musicIndex++; //目前设置无随机播放, 点击即按顺序播放下一首
            AudioSource music = audioController.GetComponent<AudioSource>();
            music.clip = ac_mc.musicList[ac_mc.musicIndex];
            music.time = 0;
            music.Play();
            //Debug.Log("ac_mc.musicIndex: " + ac_mc.musicIndex + "ac_mc.musicAmount: " + ac_mc.musicAmount);
        }
        else if(ac_mc.musicIndex == ac_mc.musicAmount -1) //如果是最后一首音乐时,则跳回重头播放
        {
            //Debug.Log("下一个判断");
            ac_mc.musicIndex = 0;
            AudioSource music = audioController.GetComponent<AudioSource>();
            music.clip = ac_mc.musicList[ac_mc.musicIndex];
            music.time = 0;
            music.Play();
        }
        else
        {
            Debug.Log("运行出错");
        }

    }

    /// <summary>
    /// 定义上一首按钮功能
    /// </summary>
    public void BackButtonController()
    {
        MusicContoller ac_mc = audioController.GetComponent<MusicContoller>();
        if (ac_mc.musicIndex > 0)
        {
            ac_mc.musicIndex--; //目前设置无随机播放, 点击即按顺序播放上一首
            AudioSource music = audioController.GetComponent<AudioSource>();
            music.clip = ac_mc.musicList[ac_mc.musicIndex];
            music.time = 0;
            music.Play();
        }
        else if (ac_mc.musicIndex == 0) //如果是最后一首音乐时,则跳回重头播放
        {
            ac_mc.musicIndex = ac_mc.musicAmount -1;
            AudioSource music = audioController.GetComponent<AudioSource>();
            music.clip = ac_mc.musicList[ac_mc.musicIndex];
            music.time = 0;
            music.Play();
        }

    }

    /// <summary>
    /// 定义音量键的功能,除此之外,在代码VolumeController中也有对音量按钮的控制,控制isdisplayVolumeSlider
    /// </summary>
    public void VolumeButtonController()
    {
        //当第一次点击音量按钮时,弹出音量条控制,再次点击则取消显示
        if (isdisplayVolumeSlider)
        {
            volumeSlider.SetActive(true);
            isdisplayVolumeSlider = false;
        }
        else
        {
            volumeSlider.SetActive(false);
            isdisplayVolumeSlider = true;
        }
    }

}

2.2.2 音量的调整控制

        为实现音乐播放的音量变化,在Volume物体上还有slider子物体,在这里会实现音量的拉动功能。对应的物体挂载如下所示。

        具体代码如下:

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 音量滑动条控制脚本
/// </summary>

public class VolumeController : MonoBehaviour
{
    [SerializeField] AudioSource audioController;
    [SerializeField] Slider volumeSlider;
    [SerializeField] Text text; //显示音量数字的文本
    [SerializeField] GameObject ControllerButton;
    private float lastDragTime;
    private bool isHidden = false;

    public void Start()
    {
        volumeSlider.value = 1;
    }

    // Update is called once per frame
    void Update()
    {
        VolumeControl();
        //2s内没拉动音量滑动条是隐藏滑动条
        ControllerButton Con_button = ControllerButton.GetComponent<ControllerButton>();
        if (Time.time - lastDragTime > 2f && !isHidden)
        {
            // 隐藏Slider
            gameObject.SetActive(false);
            isHidden = true;
            Con_button.isdisplayVolumeSlider = true; //自动隐藏也算是隐藏了,所以下一次点击就要是显示
        }
        else
        {
            // 显示Slider
            gameObject.SetActive(true);
        }
    }
    
    public void VolumeControl()
    {
        audioController.volume = volumeSlider.value;
        text.text = ((int)(volumeSlider.value * 100)).ToString(); //音量大小数字显示
    }

    public void OnSliderValueChanged()
    {
        if (isHidden)
        {
            isHidden = false;
            this.gameObject.SetActive(true);
        }
        lastDragTime = Time.time;
    }

}

2.3 音乐的播放进度条显示与控制

2.3.1 功能说明

        该部分功能包括了音乐的进度条的显示以及自动滑动、时间显示、拖动进度条等功能,同时在进度条播放结束后会自动播放下一首歌曲;还有拖动进度条是歌曲自动暂停,松开后自动播放。

        具体物体挂载如下所示。

2.3.2 音乐进度条控制代码

using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.EventSystems;

/// <summary>
/// 设计进度条功能:进度条变化、歌曲名称、时间的变化、拖拽进度条功能
/// </summary>

public class MusciProgressBar : MonoBehaviour, IDragHandler, IEndDragHandler
{
    public Slider progressBar;
    public AudioSource audioController;
    [SerializeField] private GameObject SongName;
    [SerializeField] private GameObject CoverSongName; //封面图片下方的歌曲名
    [SerializeField] private GameObject TotalTime;
    [SerializeField] private GameObject CurrentTime;
    [SerializeField] private GameObject ControllerButton;
    [SerializeField] private GameObject AudioController;
    [SerializeField] private GameObject PlayButton;
    [SerializeField] private GameObject PauseButton;
    private float progress;
    private bool isDraggingSlider = false; //定义一个bool来判断是否在拖拽进度条

    public void Start()
    { 

        progressBar.onValueChanged.AddListener(OnSliderValueChanged); //监听进度条是否被拖动
    }

    public void Update()
    { 
        //设置进度条的自动滑动
        AudioSource audio_controller = audioController.GetComponent<AudioSource>();
        if (audio_controller.isPlaying)
        {
            progress = audio_controller.time / audio_controller.clip.length; 
            Slider progress_Bar = progressBar.GetComponent<Slider>();
            progress_Bar.value = progress;

            //设置进度条上面显示的歌曲名称
            MusicContoller ac_mc = audioController.GetComponent<MusicContoller>();
            Text songname = SongName.GetComponent<Text>();
            //将输出显示格式定义为:歌曲名(1 of 8)
            songname.text = ac_mc.musicList[ac_mc.musicIndex].name + "(" + (ac_mc.musicIndex + 1) + " of " + ac_mc.musicAmount + ")";

            //设置封面图片下面的歌曲名
            Text coversongname = CoverSongName.GetComponent<Text>();
            coversongname.text = ac_mc.musicList[ac_mc.musicIndex].name;

            //设置时间的显示
            Text totalTime = TotalTime.GetComponent<Text>();
            TimeSpan total_timeSpan = TimeSpan.FromSeconds(audio_controller.clip.length); //将时间从秒数转换为为"00:00"的显示格式
            totalTime.text = string.Format("{0:D2}:{1:D2}", total_timeSpan.Minutes, total_timeSpan.Seconds);
            Text currentTime = CurrentTime.GetComponent<Text>();
            TimeSpan current_timeSpan = TimeSpan.FromSeconds(audio_controller.time);
            currentTime.text = string.Format("{0:D2}:{1:D2}", current_timeSpan.Minutes, current_timeSpan.Seconds);

        }


        //判断是否音乐已经播放结束,如果自动播放结束,则自动播放下一首
        ControllerButton con_button = ControllerButton.GetComponent<ControllerButton>();
        MusicContoller Audio_conl = AudioController.GetComponent<MusicContoller>();
        if (!audio_controller.isPlaying && !con_button.isMusicPause && Audio_conl.isStartMusicPlay) //当音乐没有播放 + 音乐不是手动暂停的 + 音乐已经进入播放进程
        {
            //Debug.Log(con_button.isMusicPause + "和" + Audio_conl.isStartMusicPlay);
            OnMusicFinished();
            //Debug.Log("结束时执行了");
        }
    }

    public void OnSliderValueChanged(float value) //定义进度条被拖动的方法
    {
        if (isDraggingSlider)
        {
            AudioSource audio_controller = audioController.GetComponent<AudioSource>();
            //Slider progress_Bar = progressBar.GetComponent<Slider>();
            audio_controller.time = (long)(value * audio_controller.clip.length); //设置视频被拖到的时间
        }

    }

    public void OnDrag(PointerEventData eventData)
    {
        //Debug.Log("进度条被拖拽中");
        isDraggingSlider = true; //进度条在拖拽时设置判断变量为真

        AudioSource au_col = audioController.GetComponent<AudioSource>();
        au_col.Pause();

        ControllerButton con_button = ControllerButton.GetComponent<ControllerButton>();
        con_button.isMusicPause = true;
        PauseButton.SetActive(true);
        PlayButton.SetActive(false);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        isDraggingSlider = false; //进度条没有在拖拽时设置判断变量为假
        //Debug.Log("进度条拖拽释放");
        AudioSource au_col = audioController.GetComponent<AudioSource>();
        au_col.Play();

        ControllerButton con_button = ControllerButton.GetComponent<ControllerButton>();
        con_button.isMusicPause = false;
        PauseButton.SetActive(false);
        PlayButton.SetActive(true);


    }

    /// <summary>
    /// 定义一个音乐播放完后自动播放下一首
    /// </summary>
    public void OnMusicFinished()
    {
        MusicContoller ac_mc = audioController.GetComponent<MusicContoller>();
        ac_mc.musicIndex++;
        if (ac_mc.musicIndex >= ac_mc.musicList.Length)
        {
            ac_mc.musicIndex = 0;
        }
        AudioSource music = audioController.GetComponent<AudioSource>();
        music.clip = ac_mc.musicList[ac_mc.musicIndex];
        music.time = 0;
        music.Play();
    }


}

3 结语

        以上的开发过程搭建思路写的可能比较简单,具体的逻辑思路都包含在了代码里了,如果要细写真的很长很长。同时这也是我初次开发音乐播放器,但是已具备完整的音乐播放功能。当然上面的代码可能仍有不完善的地方,欢迎各位大佬一同交流。

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值