unity开发简易的本地音乐播放器

由于项目需要,做了个简单的本地音乐播放器demo,记录一下,万一以后就用到了。

UI不方便贴图,只贴关键功能的代码。

功能1:从本地选择音频文件。

 这部分代码是在网上搜索到的,由于不知道原创是哪位前辈(因为所有人都标着原创),所以就不贴出处了,代码看起来感觉很懵,但是其实可以直接复制粘贴使用,只限pc端。

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public class LocalDialog {

    //链接指定系统函数       打开文件对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOFN([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }

    //链接指定系统函数        另存为对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
    public static bool GetSFN([In, Out] OpenFileName ofn)
    {
        return GetSaveFileName(ofn);
    }
}
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}

使用方式如下,LocalDialog.GetOFN(openFileName) ==true 表示选择了文件,在这里面进行操作,其中allsonglist存储了所有已经添加的文件路径,所以先判断下是否已添加。updatePlayPrefab为更新本地存储的,show为ui显示方法。

public void checkSong()
    {
        OpenFileName openFileName = new OpenFileName();
        openFileName.structSize = Marshal.SizeOf(openFileName);
        openFileName.filter = "mp3文件(*.mp3)\0*.mp3";
        openFileName.file = new string(new char[256]);
        openFileName.maxFile = openFileName.file.Length;
        openFileName.fileTitle = new string(new char[64]);
        openFileName.maxFileTitle = openFileName.fileTitle.Length;
        openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        openFileName.title = "窗口标题";
        openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;

        if (LocalDialog.GetOFN(openFileName))
        {
            if(allSongList.Contains(openFileName.file))
            {
                Tip.show("歌曲已存在,无需重复添加");
            }
            else
            {
                allSongList.Add(openFileName.file);
                updatePlayPrefab();
                show();
            }

            //Debug.Log(openFileName.fileTitle);
        }
    }

功能2:本地歌曲路径储存以及更新

即歌曲列表显示用户已经选择过的音乐,原理是用特殊字符串连接各个文件路径,然后使用PlayerPrefs存储,打开应用的时候解析数据,显示列表。下面为解析,字符串的简单处理

    const string songData = "SongListData";
    string[] sign =new string[] {"_|bzy|_" } ;//地址之间分隔符
    public void OnEnable()
    {
        allSongList = new List<string>();
        //
        if (PlayerPrefs.HasKey(songData))
        {
            string value = PlayerPrefs.GetString(songData);
            Debug.Log(value);
            string[] strArr = value.Split(sign,StringSplitOptions.None);

            for (int i = 0; i < strArr.Length; i++)
            {
                if(!string.IsNullOrEmpty( strArr[i]))
                {
                    allSongList.Add(strArr[i]);
                    Debug.Log(allSongList[i]);
                }

            }
        }
        else
        {
            PlayerPrefs.SetString(songData,"");
        }
        show();
    }

下面是存储更新,每次选择音乐以及删除的时候都要更新

    string playPrefabValue;
    void updatePlayPrefab()
    {
        playPrefabValue = string.Empty;
        string mid = string.Empty;
        for (int i = 0; i < allSongList.Count; i++)
        {
            playPrefabValue = string.Format("{0}{1}{2}", i == 0 ? "" : playPrefabValue,i == 0 ? "" : sign[0], allSongList[i]);
        }
        PlayerPrefs.SetString(songData,playPrefabValue);
    }

功能3:播放,上一首,下一首,删除

播放需要用到audiosource组件,给组件的audioclip赋值,然后调用play播放,audioclip的获取需要用到www。为了避免多次下载audioclip,应该将下载过的audioclip存储起来,这里使用了字典,key为文件路径。clip.length为时长。

int currentIndex;//当前播放的索引
    string currentSongPath;//当前播放的路径
    Dictionary<string,AudioClip> allClipList;//key path , value audioclip
    public void playMusic(string path)
    {
        CancelInvoke("playNext");
        if (allClipList == null) allClipList = new Dictionary<string, AudioClip>();

        if(string.IsNullOrEmpty(path))
        {
            currentIndex = 0;
            currentSongPath = allSongList[currentIndex];
            currentSongNameTxt.text = Path.GetFileName(currentSongPath);
        }
        else
        {
            currentIndex = allSongList.IndexOf(path);
            currentSongPath = path;
            currentSongNameTxt.text = Path.GetFileName(path);
        }

        if (allClipList.ContainsKey(currentSongPath))//clip已下载
        {
            audio.clip = allClipList[currentSongPath];
            audio.Play();
            Invoke("playNext", clip.length);
        }
        else
        {
            StartCoroutine("DownLoad");
        }
        

        //Invoke("playNext",5);
    }

    IEnumerator  DownLoad()
    {
        Debug.Log("下载。。。。");
        WWW www = new WWW("file://" + currentSongPath);
        yield return www;
        if (string.IsNullOrEmpty(www.error))
        {
            clip = www.GetAudioClip();
            allClipList.Add(currentSongPath,clip);
            audio.clip = clip;
            audio.Play();
            Invoke("playNext",clip.length);
        }
        else
        {
            Debug.LogError(www.error);
        }
    }

    //下一曲
    public void playNext()
    {
        currentIndex = (currentIndex + 1) % allSongList.Count;
        playMusic(allSongList[currentIndex]);
    }

    //上一曲
    public void playLast()
    {
        currentIndex = currentIndex == 0 ? allSongList.Count - 1 : (currentIndex - 1) % allSongList.Count;
        playMusic(allSongList[currentIndex]);
    }

删除

public void deleteSong(string path)
    {
        if (!allSongList.Contains(path))
        {
            Debug.Log("删除失败,不包含此歌曲");
        }
        else
        {
            if (allClipList.ContainsKey(path)) allClipList.Remove(path);
            allSongList.Remove(path);
            updatePlayPrefab();
            show();
        }
    }

播放模式什么的也好说,不需要也就没实现。记录结束

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值