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; } }