zoukankan      html  css  js  c++  java
  • 【学习笔记】 多线程资源管理器(附流程图附源码)

    《奇怪的大冒险》教程视频连接:
    http://www.taikr.com/course/222
    笔记结合了前7课的视频内容,感谢新总提供的免费视频
    PS:部分字段、属性和方法的命名与视频教程中有出入。

    资源管理器核心的集合一共有三个:

    1.等待加载的资源队列
    private Queue <ResLoadRequestm_QueWaitLoadAsset = new QueueResLoadRequest >();
    2.当前正在加载的资源列表
    private List <ResLoadRequestm_LstLoadingAsset = new ListResLoadRequest >();
    3.已经完成加载的资源字典
    private Dictionary <stringAssetPack > m_DicLoadedAsset = new Dictionarystring , AssetPack >();

    资源管理器的核心思想就是通过操作这三个集合,进行资源的加载,持有及释放。
    三个集合的类型,可以看到明显的差异。
    集合 <等待加载> 和 <正在加载> 的元素类型均为 ResLoadRequest类(资源加载数据类)
    集合 <完成加载> 的元素类型为 AssetPack类(资源包类)

    先从几个集合的转换,做个简要介绍
    然后是资源管理器的流程图:
    框架层级的东西,单纯看代码比较难以理解,所以我比较喜欢画图记忆,大体原理掌握了,自己也可以写出来了~!
    在这基础上还可以增加AssetBundle的资源管理器。

    另附本次学习的资源管理器代码
      1 // **********************************************************************
      2 // 
      3 // 文件名(File Name):             ResMgr.cs
      4 // 
      5 // 作者(Author):                 沐小沫
      6 // 
      7 // 日期(Create Date):             2015-07-10
      8 // 
      9 // **********************************************************************
     10 
     11 using UnityEngine;
     12 using System.Collections;
     13 using System;
     14 using System.Collections.Generic;
     15 using UnityEngine.EventSystems;
     16 
     17 public class ResMgr : MonoBehaviour
     18 {
     19     private static ResMgr m_Instance = null;                // 静态实例
     20     /// <summary>
     21     /// 获取静态实例
     22     /// </summary>
     23     /// <returns>静态实例</returns>
     24     public static ResMgr GetInstance()
     25     {
     26         return m_Instance;
     27     }
     28 
     29     private GameObject m_CachedGameObject;                  // 缓存对象
     30     private GameObject CachedGameObject
     31     {
     32         get
     33         {
     34             if (null == m_CachedGameObject && null != m_Instance)
     35             {
     36                 m_CachedGameObject = this.gameObject;
     37             }
     38 
     39             return m_CachedGameObject;
     40         }
     41     }
     42 
     43     private static int m_ProcessorCount = 0;                // 线程数量
     44     private static int ProcessorCount
     45     {
     46         set { m_ProcessorCount = Mathf.Clamp(value, 1, 8); }
     47         get { return m_ProcessorCount; }
     48     }
     49 
     50     void Awake()
     51     {
     52         ProcessorCount = SystemInfo.processorCount;
     53         DontDestroyOnLoad(CachedGameObject);
     54         m_Instance = this;
     55     }
     56 
     57     /// <summary>
     58     /// 当前正在加载的资源列表
     59     /// </summary>
     60     private List<ResLoadRequest> m_LstLoadingAsset = new List<ResLoadRequest>();
     61 
     62     /// <summary>
     63     /// 等待加载的资源队列
     64     /// </summary>
     65     private Queue<ResLoadRequest> m_QueWaitLoadAsset = new Queue<ResLoadRequest>();
     66 
     67     /// <summary>
     68     /// 已经完成加载的资源字典
     69     /// </summary>
     70     private Dictionary<string, AssetPack> m_DicLoadedAsset = new Dictionary<string, AssetPack>();
     71 
     72    
     73     /// <summary>
     74     /// 从Resources中加载一个资源
     75     /// </summary>
     76     /// <param name="assetName">资源名称</param>
     77     /// <param name="assetType">资源类型</param>
     78     /// <param name="loadListeners">加载完成的监听接口</param>
     79     /// <param name="isKeepInMemory">是否常驻内存</param>
     80     public void LoadAsset(string assetName, ILoadListeners loadListeners, Type assetType = null, bool isKeepInMemory = false)
     81     {
     82         if(string.IsNullOrEmpty(assetName))
     83         {
     84             if (null != loadListeners)
     85             {
     86                 loadListeners.Failure();
     87             }
     88             return;
     89         }
     90 
     91         if (m_DicLoadedAsset.ContainsKey(assetName))
     92         {
     93             if (null != loadListeners)
     94             {
     95                 loadListeners.Success(m_DicLoadedAsset[assetName].m_Asset);
     96             }
     97             return;
     98         }
     99 
    100         for (int i = 0; i < m_LstLoadingAsset.Count; i++)
    101         {
    102             ResLoadRequest request = m_LstLoadingAsset[i];
    103             if (request.m_AssetName.Equals(assetName))
    104             {
    105                 request.AddListeners(loadListeners);
    106                 return;
    107             }
    108         }
    109 
    110         foreach (ResLoadRequest request in m_QueWaitLoadAsset)
    111         {
    112             if (request.m_AssetName.Equals(assetName))
    113             {
    114                 request.AddListeners(loadListeners);
    115                 return;
    116             }
    117         }
    118 
    119         ResLoadRequest loadRequest = new ResLoadRequest(assetName, isKeepInMemory, assetType);
    120         loadRequest.AddListeners(loadListeners);
    121         m_QueWaitLoadAsset.Enqueue(loadRequest);
    122     }
    123 
    124     /// <summary>
    125     /// 从资源队列中处理待加载的资源
    126     /// </summary>
    127     public void Update()
    128     {
    129         if(m_LstLoadingAsset.Count > 0)
    130         {
    131             for(int i = m_LstLoadingAsset.Count - 1; i >= 0 ; i--)
    132             {
    133                 if (m_LstLoadingAsset[i].IsLoadedDone)
    134                 {
    135                     LoadAssetFinish(m_LstLoadingAsset[i]);
    136                     m_LstLoadingAsset.RemoveAt(i);
    137                 }
    138             }
    139         }
    140 
    141         while (m_LstLoadingAsset.Count < ProcessorCount && m_QueWaitLoadAsset.Count > 0)
    142         {
    143             ResLoadRequest request = m_QueWaitLoadAsset.Dequeue();
    144             m_LstLoadingAsset.Add(request);
    145             request.LoadAsync();
    146         }
    147     }
    148 
    149     /// <summary>
    150     /// 资源加载完毕
    151     /// </summary>
    152     void LoadAssetFinish(ResLoadRequest request)
    153     {
    154         if(null != request)
    155         {
    156             for (int i = 0; i < request.m_LstListeners.Count; i++)
    157             {
    158                 ILoadListeners listeners = request.m_LstListeners[i];
    159 
    160                 if (null != listeners)
    161                 {
    162                     if (null != request.m_Request && null != request.Asset)
    163                     {
    164                         listeners.Success(request.Asset);
    165 
    166                         AssetPack pack = new AssetPack(request.m_AssetType, request.m_IsKeepInMemory);
    167                         pack.m_Asset = request.Asset;
    168                         m_DicLoadedAsset.Add(request.m_AssetName, pack);
    169                     }
    170                     else
    171                     {
    172                         listeners.Failure();
    173                     }
    174                 }
    175             }
    176 
    177         }
    178     }
    179     
    180     /// <summary>
    181     /// 释放指定的资源
    182     /// </summary>
    183     /// <param name="assetName">资源名字</param>
    184     /// <param name="canRealseKeepInMemory">是否可以释放常驻内存的资源</param>
    185     public void ReleaseAsset(string assetName, bool canRealseKeepInMemory)
    186     {
    187         if (!m_DicLoadedAsset.ContainsKey(assetName))
    188         {
    189             return;
    190         }
    191 
    192         if (m_DicLoadedAsset[assetName].m_IsKeepInMemory && !canRealseKeepInMemory)
    193         {
    194             return;
    195         }
    196 
    197         m_DicLoadedAsset[assetName] = null;
    198         m_DicLoadedAsset.Remove(assetName);
    199 
    200         Resources.UnloadUnusedAssets();
    201     }
    202 
    203     /// <summary>
    204     /// 释放全部资源
    205     /// </summary>
    206     public void ReleaseAllAsset()
    207     {
    208         foreach (KeyValuePair<string, AssetPack> pair in m_DicLoadedAsset)
    209         {
    210             m_DicLoadedAsset[pair.Key] = null;
    211         }
    212 
    213         m_DicLoadedAsset.Clear();
    214         Resources.UnloadUnusedAssets();
    215     }
    216 
    217 #region 资源加载数据类
    218     /// <summary>
    219     /// 加载类
    220     /// </summary>
    221     public class ResLoadRequest
    222     {
    223         /// <summary>
    224         /// 资源名称
    225         /// </summary>
    226         public string m_AssetName;
    227 
    228         /// <summary>
    229         /// 资源类型
    230         /// </summary>
    231         public Type m_AssetType;
    232 
    233         /// <summary>
    234         /// 监听接口
    235         /// </summary>
    236         public List<ILoadListeners> m_LstListeners = new List<ILoadListeners>();
    237 
    238         /// <summary>
    239         /// 加载资源请求
    240         /// </summary>
    241         public ResourceRequest m_Request;
    242 
    243         /// <summary>
    244         /// 是否常驻内存
    245         /// </summary>
    246         public bool m_IsKeepInMemory;
    247 
    248         /// <summary>
    249         /// 重载构造函数
    250         /// </summary>
    251         /// <param name="assetName">资源名称</param>
    252         /// <param name="isKeepInMemory">是否常驻内存</param>
    253         /// <param name="assetType">资源类型</param>
    254         public ResLoadRequest(string assetName, bool isKeepInMemory, Type assetType)
    255         {
    256             this.m_AssetName = assetName;
    257             this.m_IsKeepInMemory = isKeepInMemory;
    258             this.m_AssetType = assetType;
    259         }
    260 
    261         /// <summary>
    262         /// 添加一个监听到监听列表
    263         /// </summary>
    264         /// <param name="listeners">监听接口</param>
    265         public void AddListeners(ILoadListeners listeners)
    266         {
    267             if (listeners == null)
    268             {
    269                 return;
    270             }
    271 
    272             if(!m_LstListeners.Contains(listeners))
    273             {
    274                 m_LstListeners.Add(listeners);
    275             }
    276         }
    277 
    278         /// <summary>
    279         /// 加载到的资源
    280         /// </summary>
    281         public UnityEngine.Object Asset
    282         {
    283             get
    284             {
    285                 if (null != m_Request && null != m_Request.asset)
    286                 {
    287                     return m_Request.asset;
    288                 }
    289                 else
    290                 {
    291                     return null;
    292                 }
    293             }
    294         }
    295 
    296         /// <summary>
    297         /// 当前是否已经加载完成
    298         /// </summary>
    299         public bool IsLoadedDone
    300         {
    301             get { return (null != m_Request && m_Request.isDone); }
    302         }
    303 
    304         /// <summary>
    305         /// 异步加载资源
    306         /// </summary>
    307         public void LoadAsync()
    308         {
    309             if (null == m_AssetType)
    310             {
    311                 m_AssetType = typeof(GameObject);
    312             }
    313 
    314             m_Request = Resources.LoadAsync(m_AssetName, m_AssetType);
    315         }
    316     }
    317 
    318     /// <summary>
    319     /// 资源包
    320     /// </summary>
    321     public class AssetPack
    322     {
    323         /// <summary>
    324         /// 资源类型
    325         /// </summary>
    326         public Type m_AssetType;
    327 
    328         /// <summary>
    329         /// 是否常驻内存
    330         /// </summary>
    331         public bool m_IsKeepInMemory;
    332 
    333         /// <summary>
    334         /// 资源
    335         /// </summary>
    336         public UnityEngine.Object m_Asset;
    337 
    338         public AssetPack(Type assetType, bool isKeepInMemory)
    339         {
    340             m_AssetType = assetType;
    341             m_IsKeepInMemory = isKeepInMemory;
    342         }
    343     }
    344 #endregion
    345 
    346 #region 加载资源完成后监听接口
    347 
    348     public interface ILoadListeners
    349     {
    350         /// <summary>
    351         /// 加载成功
    352         /// </summary>
    353         /// <param name="asset">资源</param>
    354         void Success(UnityEngine.Object asset);
    355 
    356         /// <summary>
    357         /// 加载失败
    358         /// </summary>
    359         void Failure();
    360     }
    361 
    362 #endregion
    363 }
  • 相关阅读:
    C++ Primer学习笔记(三) C++中函数是一种类型!!!
    C++类的成员函数的形参列表后面的const
    C++ const总结
    简单的使用Gson (序列化 和 反序化)
    HTML 获取class里的多个值 和 dataset的使用
    SiteMesh的简单使用
    IDEA 使用LiveEdit插件
    Java 转发和重定向的区别
    Web.xml 定制URL
    java 枚举类(简单使用)
  • 原文地址:https://www.cnblogs.com/muxiaomo/p/4646464.html
Copyright © 2011-2022 走看看