[펌] Music player - (load sound files at runtime from directory, and play them)
Apologies for the delay, I hit a brick wall dealing with WWW - as this is my first time I use this class, I didn't know that I had to provide the FULL path to a file for it to load it successfully.
The code is taken from here, with some modifications.
Just attach this to some gameObject
, and have your music files in your Asset folder (at edit-time) or the game folder (when you build).
It's in C#, if you have trouble translating to JS let me know.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class MusicPlayer : MonoBehaviour
{
public enum SeekDirection { Forward, Backward }
public AudioSource source;
public List<AudioClip> clips = new List<AudioClip>();
[SerializeField] [HideInInspector] private int currentIndex = 0;
private FileInfo[] soundFiles;
private List<string> validExtensions = new List<string> { ".ogg", ".wav" }; // Don't forget the "." i.e. "ogg" won't work - cause Path.GetExtension(filePath) will return .ext, not just ext.
private string absolutePath = "./"; // relative path to where the app is running - change this to "./music" in your case
void Start()
{
//being able to test in unity
if (Application.isEditor) absolutePath = "Assets/";
if (source == null) source = gameObject.AddComponent<AudioSource>();
ReloadSounds();
}
void OnGUI()
{
if (GUILayout.Button("Previous")) {
Seek(SeekDirection.Backward);
PlayCurrent();
}
if (GUILayout.Button("Play current")) {
PlayCurrent();
}
if (GUILayout.Button("Next")) {
Seek(SeekDirection.Forward);
PlayCurrent();
}
if (GUILayout.Button("Reload")) {
ReloadSounds();
}
}
void Seek(SeekDirection d)
{
if (d == SeekDirection.Forward)
currentIndex = (currentIndex + 1) % clips.Count;
else {
currentIndex--;
if (currentIndex < 0) currentIndex = clips.Count - 1;
}
}
void PlayCurrent()
{
source.clip = clips[currentIndex];
source.Play();
}
void ReloadSounds()
{
clips.Clear();
// get all valid files
var info = new DirectoryInfo(absolutePath);
soundFiles = info.GetFiles()
.Where(f => IsValidFileType(f.Name))
.ToArray();
// and load them
foreach (var s in soundFiles)
StartCoroutine(LoadFile(s.FullName));
}
bool IsValidFileType(string fileName)
{
return validExtensions.Contains(Path.GetExtension(fileName));
// Alternatively, you could go fileName.SubString(fileName.LastIndexOf('.') + 1); that way you don't need the '.' when you add your extensions
}
IEnumerator LoadFile(string path)
{
WWW www = new WWW("file://" + path);
print("loading " + path);
AudioClip clip = www.GetAudioClip(false);
while(!clip.isReadyToPlay)
yield return www;
print("done loading");
clip.name = Path.GetFileName(path);
clips.Add(clip);
}
}
Couple of notes:
You might ask, why use create a
DirectoryInfo
and then callGetFiles
on that, instead of just directly goDirectory.GetFiles(path)
? Well, the latter one will return the paths of the files inpath
, relative topath
andNOT
the full path (which is what you'll need to pass intoWWW
). i.e. if you doDirectory.GetFiles("Assets");
it will return, (for example) a string array of { "Assets/soundFile1.wav", "Assets/soundFile2.ogg", etc } - these paths are relative to "Assets" while the full path would be "E:\Dropbox\UnityStuff\MyProject...\soundFile.wav"MP3s won't work in a PC build (haven't tried wav, but it should work) see this for more info. If you want MP3s, you have to go for something more complex, like MP3Sharp,NAudio and others.
If you want to search recursively, change your
GetFiles()
call toGetFiles("*.*", SearchOption.AllDirectories)
EDIT:
JS, as per your request
import UnityEngine;
import System.Collections.Generic;
import System.IO;
import System.Linq;
public enum SeekDirection { Forward, Backward }
public var source : AudioSource;
public var clips : List.<AudioClip> = new List.<AudioClip>();
@HideInInspector @SerializeField private var currentIndex : int = 0;
private var soundFiles : FileInfo[];
private var validExtensions : List.<String> = new List.<String> ([ ".ogg", ".wav" ]);
private var absolutePath : String = "./"; // relative path to where the app is running
function Start()
{
//being able to test in unity
if (Application.isEditor)
absolutePath = "Assets/";
if (source == null)
source = gameObject.AddComponent.<AudioSource>();
ReloadSounds();
}
function OnGUI()
{
if (GUILayout.Button("Previous")) {
Seek(SeekDirection.Backward);
PlayCurrent();
}
if (GUILayout.Button("Play current")) {
PlayCurrent();
}
if (GUILayout.Button("Next")) {
Seek(SeekDirection.Forward);
PlayCurrent();
}
if (GUILayout.Button("Reload")) {
ReloadSounds();
}
}
function Seek(d : SeekDirection)
{
if (d == SeekDirection.Forward)
currentIndex = (currentIndex + 1) % clips.Count;
else {
currentIndex--;
if (currentIndex < 0) currentIndex = clips.Count - 1;
}
}
function PlayCurrent()
{
source.clip = clips[currentIndex];
source.Play();
}
function ReloadSounds()
{
clips.Clear();
// get all valid files
var info = new DirectoryInfo(absolutePath);
soundFiles = info.GetFiles()
.Where(function (f) { return IsValidFileType(f.Name); } )
.ToArray();
// and load them
for(var s in soundFiles)
StartCoroutine(LoadFile(s.FullName));
}
function IsValidFileType(fileName : String) : boolean
{
return validExtensions.Contains(Path.GetExtension(fileName));
}
function LoadFile(path : String)
{
var www = new WWW("file://" + path);
print("loading " + path);
var clip = www.GetAudioClip(false);
while(!clip.isReadyToPlay)
yield www;
print("done loading");
clip.name = Path.GetFileName(path);
clips.Add(clip);
}
[출처] http://answers.unity3d.com/questions/652919/music-player-get-songs-from-directory.html
'Unity3D > Script' 카테고리의 다른 글
Invert ParticleEffect Velocity (0) | 2016.11.09 |
---|---|
[펌] Parallax Scrolling (0) | 2016.10.27 |
[펌] OnApplicationFocus 와 OnApplicationPause 차이 (0) | 2016.09.22 |
[펌] CUSTOM COROUTINES(Unity 5.3) (0) | 2016.07.21 |
[펌] 웹서버 구현없이 클라이언트에서 실시간 처리를 해야할때 (0) | 2016.05.23 |