namespace Guru { using System; using Object = UnityEngine.Object; using UnityEngine; using System.Collections.Generic; public class GuruResManager : IResManager, IUpdater { public const string InstanceName = "guru_res_manager"; public static float CheckRequestInterval = 3; // 检查加载队列的频率 public string Name => "guru_res"; private bool _isReady; public bool IsReady => _isReady; public Context Context { get; set; } private LoaderPool _loaderPool; private Queue _requests; /// /// 注册资源管理器 /// /// /// public static GuruResManager Create(Context context) { var mgr = new GuruResManager(); mgr.Init(); context.RegisterResManager(mgr, InstanceName); return mgr; } public void Init() { _isReady = true; _loaderPool = LoaderPool.CreatePool(); _requests = new Queue(20); } public T CloneObject(GameObject prefab, Transform container = null) where T :Component { var go = GameObject.Instantiate(prefab, container); if (go != null) { go.name = nameof(T).ToLower(); return go.GetComponent(); } return null; } /// /// 加载本地资源 /// /// /// /// public T Load(string resUri) where T : Object { return Resources.Load(resUri); } /// /// 异步加载资源 /// /// /// /// public void LoadAsync(string resUri, Action onLoadComplete) { ResRequest req = ResRequest.Create(resUri, onLoadComplete); _requests.Enqueue(req); // 添加任务 } #region 帧更新 /// /// 帧更新 /// public void OnUpdate() { CheckLoadingList(); } public bool IsStopped { get; set; } = false; #endregion #region 加载队列 private float _checkLoadingDuration = 0; /// /// 检查加载队列 /// private void CheckLoadingList() { if (_requests.Count > 0 && _loaderPool.FreeCount > 0) { _checkLoadingDuration = 0; } // 更新检查队列 if (_checkLoadingDuration > 0) { _checkLoadingDuration -= Time.deltaTime; return; } // 检查队列 while (_requests.Count > 0 && _loaderPool.FreeCount > 0) { var loader = _loaderPool.Get(); if (loader != null) { var req = _requests.Dequeue(); loader.LoadAsync(req.resUri, req.callback); } } _checkLoadingDuration = CheckRequestInterval; } #endregion } /// /// 加载器池 /// 默认同时持有 3 个加载器 /// internal class LoaderPool: IPool { public string Name => "loader_pool"; public int PreSpawnCount { get; set; } = 3; private Queue _freeLoaders; public static LoaderPool CreatePool(int initCount = 3) { if (initCount < 2) initCount = 2; // 最小 2 个 var pool = new LoaderPool(initCount); return pool; } public LoaderPool(int initCount = 0) { if (initCount > 0) PreSpawnCount = initCount; _freeLoaders = new Queue(); if (PreSpawnCount > 0) { for (int i = 0; i < PreSpawnCount; i++) { _freeLoaders.Enqueue(Create()); } } } public ResLoaderBase Get() { if(FreeCount > 0) { return _freeLoaders.Dequeue(); } return null; } public ResLoaderBase Create() { var loader = new ResLoaderBase(); loader.OnLoaderFree = Recycle; return loader; } public void Recycle(ResLoaderBase obj) { _freeLoaders.Enqueue(obj); } public int FreeCount => _freeLoaders.Count; } /// /// 加载需求 /// internal struct ResRequest { public string url; public string resUri; public Action callback; public static ResRequest Create(string resUri, Action callback) { ResUriHelper.UriToType(resUri, out var type, out var url); return new ResRequest() { url = url, resUri = resUri, callback = callback }; } } }