游戏资源管理

作者:追风剑情 发布于:2021-8-30 17:19 分类:Unity3d

资源管理模块




using UnityEngine;

namespace XFramework
{
    /// <summary>
    /// 资源模块
    /// 对各类资源的管理:
    /// Texture、TextAsset、GameObject、AudioClip、ScriptObject、Scene
    /// </summary>
    public class AssetModule : MonoBehaviour
    {
        //资源加载器
        private AssetLoader _assetLoader = new AssetLoader();
        //场景加载器
        private SceneLoader _sceneLoader = new SceneLoader();
        //配置加载器
        private ConfigLoader _configLoader = new ConfigLoader();

        public AssetLoader GetAssetLoader()
        {
            return _assetLoader;
        }

        public SceneLoader GetSceneLoader()
        {
            return _sceneLoader;
        }

        public ConfigLoader GetConfigLoader()
        {
            return _configLoader;
        }

        private void Update()
        {
            _assetLoader.Update();
            _sceneLoader.Update();
            _configLoader.Update();
        }

        //从场景中找到资源模块
        public static AssetModule FindAssetModule()
        {
            GameObject go = GameObject.Find("AssetModule");
            if (go == null)
                return null;
            return go.GetComponent<AssetModule>();
        }
    }
}




using System;
using System.Collections.Generic;

namespace XFramework
{
    //资源加载器
    public class AssetLoader
    {
        private List<AssetLoadItem> _loadList = new List<AssetLoadItem>();

        public void Update()
        {
            if (_loadList.Count == 0)
                return;

            for (int i = 0; i < _loadList.Count; i++)
            {
                var item = _loadList[i];
                if (item.IsDisposed)
                {
                    _loadList.RemoveAt(i);
                    break;
                }

                if (!item.IsDone)
                {
                    item.RaiseProgress();
                    continue;
                }

                if (item.IsError)
                {
                    item.RaiseError();
                    item.Dispose();
                    _loadList.RemoveAt(i);
                    break;
                }

                item.RaiseCompleted();
                item.Dispose();
                _loadList.RemoveAt(i);
                break;
            }
        }

        //异步加载
        public void LoadAsync(string url, Action<AssetItem> callback, Action<string, float> callprogress = null, Action<string, string> errorback = null, AssetType assetType = AssetType.None)
        {
            AssetLoadItem item = new AssetLoadItem();
            item.OnCompleted = callback;
            item.OnProgress = callprogress;
            item.OnError = errorback;
            item.assetType = assetType;
            item.Load(url);
            _loadList.Add(item);
        }

        public void LoadAsync(string[] urlArr, Action<AssetItem> callback, Action<string, float> callprogress = null, Action<string, string> errorback = null, AssetType assetType = AssetType.None)
        {
            if (urlArr == null || urlArr.Length == 0)
                return;
            for (int i = 0; i < urlArr.Length; i++)
                LoadAsync(urlArr[i], callback, callprogress, errorback, assetType);
        }

        //中止加载
        public void LoadAbort(string url)
        {
            if (string.IsNullOrEmpty(url))
                return;
            for (int i = 0; i < _loadList.Count; i++)
            {
                if (_loadList[i].Url == url)
                {
                    _loadList[i].Dispose();
                    break;
                }
            }
        }
    }
}





using System;
using System.IO;
using UnityEngine;

namespace XFramework
{
    //资源加载项
    public class AssetLoadItem
    {
        public static string[] invalidExtension = { 
            ".pdf", ".docx", ".xlsx", ".doc", ".xls", ".pptx", "ppt", ".wps" };
        public static string[] textureExtension = { 
            ".jpg", ".jpeg", ".png", ".bmp", ".tga" };
        public static string[] textExtension = { ".txt" };
        public static string[] assetBundleExtension = { ".model", ".tex" };

        public Action<AssetItem> OnCompleted;
        public Action<string, string> OnError;
        public Action<string, float> OnProgress;
        public AssetType assetType;
        private WWW www;
        private bool _disposed = false;

        public string Url
        {
            get
            {
                if (www == null) return string.Empty;
                else return www.url;
            }
        }
        public bool IsDone { get { return www.isDone; } }
        public bool IsError { get { return !string.IsNullOrEmpty(www.error); } }
        public float Progress { get { return www.progress; } }
        public bool IsDisposed { get { return _disposed; } }

        //格式化协议地址
        public static string FormatProtocolURL(string url)
        {
            //网络地址
            if (url.StartsWith("http://"))
                return url;
            //本地地址
            if (!url.StartsWith("file://") && !url.StartsWith("jar:file:///"))
                url = "file://" + url;
            return url;
        }

        public void Load(string url)
        {
            if (AssetCache.enabled && AssetCache.HasCache(url))
                url = AssetCache.GetCachePath(url);
            url = FormatProtocolURL(url);
            www = new WWW(url);
        }

        public void RaiseProgress()
        {
            if (www == null)
                return;
            OnProgress?.Invoke(www.url, www.progress);
        }

        public void RaiseCompleted()
        {
            if (www == null)
                return;

            string fileName = Path.GetFileNameWithoutExtension(www.url);
            AssetItem item = new AssetItem();
            item.url = www.url;
            item.bytes = www.bytes;
            item.Cache();

            //根据后缀判断文件类型
            string ext = Path.GetExtension(www.url).ToLower();
            if (assetType == AssetType.Text || IsTextExt(ext))
            {
                TextAsset textAsset = new TextAsset(www.text);
                item.SetObject(textAsset);
            }
            else if (assetType == AssetType.Texture || IsTextureExt(ext))
            {
                item.SetObject(www.texture);
            }
            else if (assetType == AssetType.AssetBundle || IsAssetBundleExt(ext))
            {
                AssetBundle ab = www.assetBundle;
                var obj = ab.LoadAsset(fileName);
                item.SetObject(obj);
                ab.Unload(false);//释放镜像资源
            }
            else if(IsInvalidExtension(ext))
            {

            }
            OnCompleted?.Invoke(item);
        }

        // 是否为AssetBundle文件
        public static bool IsAssetBundleExt(string ext)
        {
            return Array.Exists(assetBundleExtension, element => element == ext);
        }

        // 是否为Texture文件
        public static bool IsTextureExt(string ext)
        {
            return Array.Exists(textureExtension, element => element == ext);
        }

        // 是否为Text文件
        public static bool IsTextExt(string ext)
        {
            return Array.Exists(textExtension, element => element == ext);
        }

        // 是否为无效后缀文件
        public static bool IsInvalidExtension(string ext)
        {
            return Array.Exists(invalidExtension, element => element == ext);
        }

        public void RaiseError()
        {
            if (www == null)
                return;
            if (OnError == null)
                Debug.LogErrorFormat("{0}\n{1}", www.error, www.url);
            OnError?.Invoke(www.url, www.error);
        }

        public void Dispose()
        {
            if (www != null)
            {
                www.Dispose();
                www = null;
            }
            OnCompleted = null;
            OnError = null;
            OnProgress = null;
            _disposed = true;
        }
    }

    //资源类型
    public enum AssetType
    {
        None,
        Text,
        Texture,
        Audio,
        AssetBundle,
        Binary
    }
}





using System;
using UnityEngine;
using UnityEngine.U2D;
using UnityObject = UnityEngine.Object;

namespace XFramework
{
    //通用资源项
    [Serializable]
    public class AssetItem
    {
        public string url;
        public GameObject gameObject;
        public TextAsset textAsset;
        public AudioClip audioClip;
        public Texture2D texture2D;
        public SpriteAtlas spriteAtlas;
        public ScriptableObject scriptableObject;
        public byte[] bytes;

        public void SetObject(UnityObject obj)
        {
            if (obj is GameObject)
            {
                gameObject = obj as GameObject;
                //必须要Instantiate一个出来才能在场景中使用
                gameObject = GameObject.Instantiate<GameObject>(gameObject);
            }
            else if (obj is TextAsset)
                textAsset = obj as TextAsset;
            else if (obj is AudioClip)
                audioClip = obj as AudioClip;
            else if (obj is Texture2D)
                texture2D = obj as Texture2D;
            else if (obj is SpriteAtlas)
                spriteAtlas = obj as SpriteAtlas;
            else if (obj is ScriptableObject)
                scriptableObject = obj as ScriptableObject;
        }

        public void Cache()
        {
            AssetCache.Write(url, bytes);
        }
    }
}




using System;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;

namespace XFramework
{
    /// <summary>
    /// 场景加载器
    /// </summary>
    public class SceneLoader
    {
        private Action<string> OnLoadCompleted;
        private Action<float> OnLoadProgress;
        private Action<string> OnLoadError;

        private UnityWebRequest request;
        private UnityWebRequestAsyncOperation requestAsync;
        private AsyncOperation sceneAsync;
        private AssetBundle assetBundle;
        public string url { get; private set; }

        public void Update()
        {
            if (request == null)
                return;

            if (!request.isDone)
            {
                OnLoadProgress?.Invoke(request.downloadProgress);
                return;
            }

            if (request.isNetworkError || request.isHttpError)
            {
                OnLoadError?.Invoke(request.error);
                Dispose();
                return;
            }
        }

        public void LoadAsync(string url, Action<string> callback = null, Action<float> progressback = null, Action<string> errorback = null)
        {
            this.url = url;
            OnLoadCompleted = callback;
            OnLoadProgress = progressback;
            OnLoadError = errorback;
            UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url);
            requestAsync = request.SendWebRequest();
            requestAsync.completed += OnWebRequestAssetBundle;
        }

        private void OnWebRequestAssetBundle(AsyncOperation async)
        {
            async.completed -= OnWebRequestAssetBundle;
            var req_async = async as UnityWebRequestAsyncOperation;
            var webRequest = req_async.webRequest;
            try
            {
                assetBundle = DownloadHandlerAssetBundle.GetContent(webRequest);
            }
            catch (Exception e)
            {
                //网络错误
                OnLoadError?.Invoke(string.Format("{0}\n{1}", e.Message, url));
                Dispose();
                return;
            }
            string sceneName = Path.GetFileNameWithoutExtension(webRequest.url);
            sceneAsync = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
            if (sceneAsync == null)
            {
                //url错误(资源不存在)
                OnLoadError?.Invoke("scene couldn't be loaded\n" + url);
                Dispose();
                return;
            }
            sceneAsync.allowSceneActivation = true;
            sceneAsync.completed += OnLoadSceneAsyncCompleted;
        }

        private void OnLoadSceneAsyncCompleted(AsyncOperation async)
        {
            Debug.Log("[SceneLoader] OnLoadSceneAsyncCompleted");
            async.completed -= OnLoadSceneAsyncCompleted;
            OnLoadCompleted?.Invoke(url);
            Dispose();
        }

        private void Dispose()
        {
            if (requestAsync != null)
                requestAsync.completed -= OnWebRequestAssetBundle;
            requestAsync = null;

            if (sceneAsync != null)
                sceneAsync.completed -= OnLoadSceneAsyncCompleted;
            sceneAsync = null;

            if (request != null)
                request.Dispose();
            request = null;

            if (assetBundle != null)
            {
                Debug.Log("Unload the scene assetBundle");
                assetBundle.Unload(false);//释放镜像资源
                assetBundle = null;
            }

            OnLoadCompleted = null;
            OnLoadProgress = null;
            OnLoadError = null;
        }
    }
}





using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace XFramework
{
    /// <summary>
    /// 配置加载器
    /// </summary>
    public class ConfigLoader
    {
        private Action<List<ConfigItem>> OnCompleted;
        private Action<string, string> OnError;
        private Action<string, float> OnProgress;

        //要加载的配置文件地址
        private List<string> _urlList;
        private List<ConfigItem> _configList;

        private AssetLoader _assetLoader = new AssetLoader();

        public void LoadAsync(List<string> urlList, Action<List<ConfigItem>> callback, Action<string, float> callprogress = null, Action<string, string> errorback = null)
        {
            _urlList = urlList;
            OnCompleted = callback;
            OnProgress = callprogress;
            OnError = errorback;
            LoadConfig();
        }

        private void LoadConfig()
        {
            if (_urlList == null || _urlList.Count == 0)
            {
                OnCompleted?.Invoke(null);
                return;
            }

            if (_configList == null)
                _configList = new List<ConfigItem>();

            _assetLoader.LoadAsync(_urlList.ToArray(),
                //成功
                (assetItem) => {
                    ConfigItem item = new ConfigItem();
                    item.url = assetItem.url;
                    item.name = Path.GetFileNameWithoutExtension(assetItem.url);
                    item.content = assetItem.textAsset.text;
                    _configList.Add(item);

                    if (_configList.Count == _urlList.Count)
                        OnCompleted?.Invoke(_configList);
                },
                //进度
                (assetUrl, progress) =>
                {
                    float segment = 1.0f / (float)_urlList.Count;
                    //当前总进度
                    float all_progress = segment * _configList.Count + segment * progress;
                    OnProgress?.Invoke(assetUrl, all_progress);
                },
                //失败
                (assetUrl, error) => {
                    Debug.LogErrorFormat("{0}\n{1}", error, assetUrl);
                    OnError?.Invoke(assetUrl, error);
                },
                AssetType.Text);
        }

        public void Update()
        {
            _assetLoader.Update();
        }
    }

    public class ConfigItem
    {
        public string url;
        public string name;
        public string content;
    }
}




using System;
using System.IO;
using UnityEngine;
/// <summary>
/// 资源缓存
/// </summary>
public sealed class AssetCache
{
    public static bool enabled = true;

    //资源缓存目录
    public static string CacheDirectory
    {
        get
        {
            string cachePath = Path.Combine(Application.persistentDataPath, "cache");
            if (!Directory.Exists(cachePath))
                Directory.CreateDirectory(cachePath);
            return cachePath;
        }
    }

    //是否存在缓存资源
    public static bool HasCache(string url)
    {
        string filePath = GetCachePath(url);
        return File.Exists(filePath);
    }

    //获取缓存资源路径
    public static string GetCachePath(string url)
    {
        string fileName = Path.GetFileName(url);
        string filePath = Path.Combine(CacheDirectory, fileName);
        return filePath;
    }

    //缓存资源
    public static void Write(string url, byte[] bytes)
    {
        if (!enabled)
            return;
        if (string.IsNullOrEmpty(url))
            return;
        if (bytes == null || bytes.Length == 0)
            return;
        string filePath = GetCachePath(url);
        File.WriteAllBytes(filePath, bytes);
    }

    //是否为图片资源
    public static bool IsTexture(string url)
    {
        string[] tex_exts = new string[] { ".png", ".jpg", ".jpeg", ".bmp" };
        string ext = Path.GetExtension(url).ToLower();
        bool exists = Array.Exists(tex_exts, 
            new Predicate<string>((element)=> { return element == ext; }));
        return exists;
    }

    //是否为视频资源
    public static bool IsVideo(string url)
    {
        string[] video_exts = new string[] {
            ".mov", ".mpg", ".mpeg", ".mp4", ".avi", ".asf"};
        string ext = Path.GetExtension(url).ToLower();
        bool exists = Array.Exists(video_exts,
            new Predicate<string>((element) => { return element == ext; }));
        return exists;
    }
}

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号