213 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C#
		
	
	
| 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<ResRequest> _requests;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 注册资源管理器
 | |
|         /// </summary>
 | |
|         /// <param name="context"></param>
 | |
|         /// <returns></returns>
 | |
|         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<ResRequest>(20);
 | |
|         }
 | |
|         
 | |
|         public T CloneObject<T>(GameObject prefab, Transform container = null) where T :Component
 | |
|         {
 | |
|             var go = GameObject.Instantiate<GameObject>(prefab, container);
 | |
|             if (go != null)
 | |
|             {
 | |
|                 go.name = nameof(T).ToLower();
 | |
|                 return go.GetComponent<T>();
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 加载本地资源
 | |
|         /// </summary>
 | |
|         /// <param name="resUri"></param>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <returns></returns>
 | |
|         public T Load<T>(string resUri) where T : Object
 | |
|         {
 | |
|             return Resources.Load<T>(resUri);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步加载资源
 | |
|         /// </summary>
 | |
|         /// <param name="resUri"></param>
 | |
|         /// <param name="onLoadComplete"></param>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         public void LoadAsync(string resUri, Action<ResLoadInfo> onLoadComplete)
 | |
|         {
 | |
|             ResRequest req =  ResRequest.Create(resUri, onLoadComplete);
 | |
|             _requests.Enqueue(req); // 添加任务
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
|         #region 帧更新
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 帧更新
 | |
|         /// </summary>
 | |
|         public void OnUpdate()
 | |
|         {
 | |
|             CheckLoadingList();
 | |
|         }
 | |
| 
 | |
|         public bool IsStopped { get; set; } = false;
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
| 
 | |
| 
 | |
|         #region 加载队列
 | |
| 
 | |
|         private float _checkLoadingDuration = 0;
 | |
|         /// <summary>
 | |
|         /// 检查加载队列
 | |
|         /// </summary>
 | |
|         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
 | |
|         
 | |
|         
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// 加载器池
 | |
|     /// 默认同时持有 3 个加载器
 | |
|     /// </summary>
 | |
|     internal class LoaderPool: IPool<ResLoaderBase>
 | |
|     {
 | |
|         public string Name => "loader_pool";
 | |
|         public int PreSpawnCount { get; set; } = 3;
 | |
|         private Queue<ResLoaderBase> _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<ResLoaderBase>();
 | |
|             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;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// 加载需求
 | |
|     /// </summary>
 | |
|     internal struct ResRequest
 | |
|     {
 | |
|         public string url;
 | |
|         public string resUri;
 | |
|         public Action<ResLoadInfo> callback; 
 | |
|         
 | |
|         public static ResRequest Create(string resUri, Action<ResLoadInfo> callback)
 | |
|         {
 | |
|             ResUriHelper.UriToType(resUri, out var type, out var url);
 | |
|             return new ResRequest()
 | |
|             {
 | |
|                 url = url,
 | |
|                 resUri = resUri,
 | |
|                 callback = callback
 | |
|             };
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
| } |