using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
/// <summary>
/// 资源加载器
/// 从 Application.streamingAssetsPath 下加载文件
/// </summary>
public class StreamingAssetsLoader : MonoBehaviour
{
//文件url列表,只填写相对路径
[SerializeField]
private List<string> m_urls = new List<string>();
//是否执行Awake方法时自动开始加载
[SerializeField]
private bool m_LoadOnAwake = false;
public string url { get; private set; }
public string error { get; private set; }
public float progress { get; private set; }
public AssetObject asset { get; private set; }
[Serializable]
public class FileProgressEvent : UnityEvent<StreamingAssetsLoader> { }
[Serializable]
public class FileCompletedEvent : UnityEvent<StreamingAssetsLoader> { }
[Serializable]
public class FileErrorEvent : UnityEvent<StreamingAssetsLoader> { }
[Serializable]
public class ListCompletedEvent : UnityEvent<StreamingAssetsLoader> { }
//当前文件加载进度
[FormerlySerializedAs("onFileProgress")]
[SerializeField]
private FileProgressEvent m_OnFileProgress = new FileProgressEvent();
//当前文件加载完成
[FormerlySerializedAs("onFileCompleted")]
[SerializeField]
private FileCompletedEvent m_OnFileCompleted = new FileCompletedEvent();
//所有文件加载完成
[FormerlySerializedAs("onListCompleted")]
[SerializeField]
private ListCompletedEvent m_OnListCompleted = new ListCompletedEvent();
//当前文件加载出错
[FormerlySerializedAs("onFileError")]
[SerializeField]
private FileErrorEvent m_OnFileError = new FileErrorEvent();
public FileProgressEvent OnFileProgress => m_OnFileProgress;
public FileCompletedEvent OnFileCompleted => m_OnFileCompleted;
public ListCompletedEvent OnListCompleted => m_OnListCompleted;
public FileErrorEvent OnFileError => m_OnFileError;
//资源类型
public enum AssetType
{
None = 0,//未知
Text, //文本
Texture,//图片
Audio, //音频
AssetBundle, //资源包
}
//资源对象
public class AssetObject
{
public AssetType type;
public string url;
public string text;
public Texture2D texture;
public AudioClip audioClip;
public AssetBundle assetBundle;
public void Dispose()
{
texture = null;
audioClip = null;
assetBundle = null;
}
}
private void Awake()
{
if (m_LoadOnAwake)
StartLoad();
}
// 清空url
public void Clear()
{
m_urls.Clear();
if (asset != null)
{
asset.Dispose();
asset = null;
}
}
// 设置urls
public void SetUrls(List<string> urls)
{
m_urls = urls;
}
// 添加url
public void AddUrl(string url)
{
m_urls.Add(url);
}
// 启动加载
public void StartLoad()
{
StartCoroutine(LoadAsync());
}
// 停止加载
public void StopLoad()
{
StopCoroutine(LoadAsync());
}
private IEnumerator LoadAsync()
{
yield return null;
int index = 0;
while (index < m_urls.Count)
{
url = m_urls[index++];
url = string.Format("{0}/{1}", Application.streamingAssetsPath, url);
Debug.LogFormat("Load: {0}", url);
WWW www = new WWW(url);
while (!www.isDone)
{
progress = www.progress;
m_OnFileProgress?.Invoke(this);
yield return www;
}
if (!string.IsNullOrEmpty(www.error))
{
error = www.error;
m_OnFileError?.Invoke(this);
yield break;
}
AssetObject obj = new AssetObject();
obj.url = url;
obj.type = GetAssetTypeByExtension(url);
ReadFromWWW(obj, www);
asset = obj;
www.Dispose();
m_OnFileCompleted?.Invoke(this);
yield return new WaitForEndOfFrame();
}
m_OnListCompleted?.Invoke(this);
}
private void OnDestroy()
{
StopAllCoroutines();
}
// 从www中读取资源
private void ReadFromWWW(AssetObject obj, WWW www)
{
switch (obj.type)
{
case AssetType.Text:
obj.text = www.text;
break;
case AssetType.Texture:
obj.texture = www.texture;
break;
case AssetType.Audio:
obj.audioClip = www.GetAudioClip();
break;
case AssetType.AssetBundle:
obj.assetBundle = www.assetBundle;
break;
}
}
// 通过后缀判断资源类型
private AssetType GetAssetTypeByExtension(string url)
{
string ext = Path.GetExtension(url).ToLower();
if (ext.Equals(".tif") || ext.Equals(".jpg") || ext.Equals(".png"))
return AssetType.Texture;
if (ext.Equals(".txt") || ext.Equals(".json") || ext.Equals(".xml"))
return AssetType.Text;
if (ext.Equals(".wav") || ext.Equals(".mp3"))
return AssetType.Audio;
//资源包文件后缀,根据需求定义
if (ext.Equals(".model"))
return AssetType.AssetBundle;
return AssetType.None;
}
}