zoukankan      html  css  js  c++  java
  • Unity5系列资源管理AssetBundle——加载

    上次我们进行了AssetBundle打包,现在我们还把打包的资源加载到我们的游戏中。
    在加载之前,我们需要把打包好的Bundle包裹放到服务器上,如果没有,也可以使用XAMPP搭建本地服务器。

    加载的AssetBundle文件是放在内存中的,所以如果没有很好的管理,会使游戏性能大打折扣,因此,我们在这里最好使用缓存策略。

    我们的AssetBundle:

     1 using System;
     2 using UnityEngine;
     3  
     4 namespace MrCAssetFramework
     5 {
     6     public sealed class MrCAssetBundle
     7     {
     8         internal AssetBundle m_AssetBundle;
     9         internal string      m_AssetBundleName;
    10         internal MrCAssetBundle(AssetBundle assetBundle,string name)
    11         {
    12             this.m_AssetBundle = assetBundle;
    13             this.m_AssetBundleName = name;
    14             this.m_ReferencedCount = 1;
    15         }
    16          
    17         #region ReferenceCountManage
    18         //yinyongjishujizhi
    19         private int m_ReferencedCount;
    20         public void Retain()
    21         {
    22             this.m_ReferencedCount++;
    23         }
    24         public void Release(){
    25             this.m_ReferencedCount--;
    26             //当引用计数为0时,卸载资源
    27             if (this.m_ReferencedCount == 0) 
    28             {
    29                 this.m_AssetBundle.Unload (true);
    30                 MrCAssetCache.FreeBundle(this.m_AssetBundleName);
    31             }
    32         }
    33          
    34         public int RetainCount()
    35         {
    36             return this.m_ReferencedCount;
    37         }
    38         #endregion
    39          
    40     }
    41 }

    AssetBundle管理:

      1 using System;
      2 using UnityEngine;
      3 using System.Collections;
      4 using System.Collections.Generic;
      5  
      6 namespace MrCAssetFramework
      7 {   
      8     public class MrCAssetManager:MonoBehaviour
      9     {
     10  
     11         #region Singleton
     12         private static GameObject       s_go_MrCAssetManager = null;
     13         private static MrCAssetManager  s_MrCAssetManager = null;
     14  
     15         public static MrCAssetManager DefaultAssetManager{
     16             get{
     17                 if (s_MrCAssetManager == null) {
     18                     s_go_MrCAssetManager = new GameObject ("LOAssetManager");
     19                     s_MrCAssetManager = s_go_MrCAssetManager.AddComponent<MrCAssetManager> ();
     20                 }
     21  
     22                 return s_MrCAssetManager;
     23             }
     24         }
     25  
     26         #endregion
     27  
     28         public  static string URI{ set; get;}
     29         public static string ManifestName{ set; get;}
     30         //无返回值泛型委托..
     31         public static Action<bool> InitBlock;
     32  
     33         public AssetBundleManifest manifest{ set; get;}
     34  
     35          36      ///<summary>
     37         /// To get the asset..
     38         /// </summary>
     39  
     40         /// <returns>The asset..</returns>
     41         public T GetAsset<T>(string assetbundlename,string assetname) where T:UnityEngine.Object
     42         {
     43             MrCAssetBundle lab = MrCAssetCache.GetBundleCache(assetbundlename);
     44  
     45             if (lab == null) {
     46                 return null;
     47             }
     48             else
     49             {
     50                 return lab.m_AssetBundle.LoadAsset<T>(assetname);
     51             }
     52         }
     53  
     54         IEnumerator LoadManifestBundle()
     55         {
     56             //缓存中已经存在请求的bundle,中止..
     57             if (MrCAssetCache.InCache(MrCAssetManager.ManifestName)) {
     58                 yield break;
     59             }
     60  
     61             // 通过网络下载AssetBundle
     62             WWW www = IsLoadAssetBundleAtInternal(MrCAssetManager.ManifestName);
     63             yield return www;
     64  
     65             this.manifest = this.GetAsset<AssetBundleManifest>(MrCAssetManager.ManifestName,"AssetBundleManifest");
     66             MrCAssetManager.InitBlock (this.manifest != null);
     67         }
     68         void Start()
     69         {
     70             StartCoroutine ("LoadManifestBundle");
     71         }
     72  
     73  
     74  
     75  
     76         #region 加载包裹系列函数
     77  
     78          79      ///<summary>
     80         /// 检查是否已经从网络下载
     81         /// </summary>
     82  
     83         protected WWW IsLoadAssetBundleAtInternal (string assetBundleName)
     84         {
     85             //已经存在了呀
     86             MrCAssetBundle bundle = MrCAssetCache.GetBundleCache(assetBundleName);
     87             if (bundle != null)
     88             {
     89                 //保留数加一次
     90                 bundle.Retain ();
     91                 return null;
     92             }
     93  
     94             //如果WWW缓存策略中包含有对应的关键字,则返回true
     95             if (MrCAssetCache.InCache (assetBundleName)) {
     96                 return null;
     97             }
     98  
     99             //创建下载链接
    100             WWW www = new WWW(MrCAssetManager.URI + assetBundleName);
    101             // 按版本号,按需要通过网络下载AssetBundle,一般在正式游戏版本中,不使用上面的,因为它会每次打开游戏重新下载
    102             //WWW www = WWW.LoadFromCacheOrDownload(LOAssetManager.URI + assetBundleName, nowVersion);
    103  
    104             //加入缓存策略
    105             MrCAssetCache.SetWWWCache(assetBundleName,www);
    106  
    107             return www;
    108         }
    109  
    110  
    111         IEnumerator LoadDependencies(string assetBundleName)
    112         {
    113             if (this.manifest == null) {
    114                 yield return null;
    115             }
    116             // 获取依赖包裹
    117             string[] dependencies = this.manifest.GetAllDependencies(assetBundleName);
    118  
    119             Debug.Log(dependencies.Length);
    120  
    121             if (dependencies.Length == 0)
    122             {
    123                 yield return null;
    124             }
    125  
    126             // 记录并且加载所有的依赖包裹
    127             MrCAssetCache.SetDependCache(assetBundleName, dependencies);
    128  
    129             for (int i = 0; i < dependencies.Length; i++) 
    130             {
    131                 yield return IsLoadAssetBundleAtInternal (dependencies [i]);
    132             }
    133         }
    134  
    135         136      /// <summary>
    137         /// 加载资源包
    138         /// </summary>
    139  
    140         IEnumerator LoadAssetBundle(string assetBundleName)
    141         {
    142             if (MrCAssetCache.InCache(assetBundleName)) {
    143                 yield break;
    144             }
    145             // 通过网络下载AssetBundle
    146             WWW www = IsLoadAssetBundleAtInternal(assetBundleName);
    147             yield return www;
    148  
    149             // 通过网络加载失败,下载依赖包裹
    150             yield return StartCoroutine(LoadDependencies(assetBundleName));
    151         }
    152  
    153         154      ///<summary>
    155         /// 异步加载资源
    156         /// </summary>
    157  
    158         public IEnumerator LoadAssetAsync (string assetBundleName, string assetName, System.Type type)
    159         {
    160             //开始加载包裹
    161             yield return StartCoroutine(LoadAssetBundle (assetBundleName));
    162         }
    163  
    164         165      ///<summary>
    166         /// 异步加载场景
    167         /// </summary>
    168  
    169         public IEnumerator LoadLevelAsync (string assetBundleName, string levelName, bool isAdditive)
    170         {
    171             //加载资源包
    172             yield return StartCoroutine(LoadAssetBundle (assetBundleName));
    173  
    174         }
    175         #endregion
    176  
    177  
    178         #region Update
    179  
    180         void Update()
    181         {
    182             MrCAssetCache.Update();
    183         }
    184         #endregion
    185     }
    186 }

    缓存管理:

      1 using System;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4  
      5 namespace MrCAssetFramework
      6 {
      7     internal sealed class MrCAssetCache
      8     {
      9         #region 包裹缓存机制
     10         //创建缓存字典
     11         private static Dictionary<string, MrCAssetBundle> assetBundleCache;
     12         //缓存字典属性
     13         private static Dictionary<string, MrCAssetBundle> BundleCache
     14         {
     15             get{ 
     16                 if (assetBundleCache == null) {
     17                     assetBundleCache = new Dictionary<string, MrCAssetBundle> ();
     18                 }
     19                  
     20                 return assetBundleCache;
     21             }
     22         }
     23          
     24         //创建缓存WWW对象
     25         private static Dictionary<string, WWW> wwwCache;
     26         //创建缓存WWW对象属性
     27         private static Dictionary<string, WWW> WwwCache{
     28             get{ 
     29                 if (wwwCache == null) {
     30                     wwwCache = new Dictionary<string, WWW> ();
     31                 }
     32                  
     33                 return wwwCache;
     34             }
     35         }
     36         //创建依赖缓存对象
     37         private static Dictionary<string, string[]> dependCache;
     38         //创建依赖缓存属性
     39         private static Dictionary<string, string[]> DependCache
     40         {
     41             get{ 
     42                 if (dependCache == null) {
     43                     dependCache = new Dictionary<string, string[]> ();
     44                 }
     45                 return dependCache;
     46             }
     47         }
     48          
     49         private static Dictionary<string, string> errorCache;
     50         private static Dictionary<string,string> ErrorCache{
     51             get{ 
     52                 if (errorCache == null) {
     53                     errorCache = new Dictionary<string, string> ();
     54                 }
     55                 return errorCache;
     56             }
     57         }
     58  
     59          60      ///<summary>
     61         /// Instantiate the cache.
     62         /// </summary>
     63  
     64         /// <returns><c>true</c>, if cache was ined, <c>false</c> otherwise.</returns>
     65         /// <param name="assetbundlename">Assetbundlename.</param>
     66         internal static bool InCache(string assetbundlename)
     67         {
     68             return MrCAssetCache.BundleCache.ContainsKey(assetbundlename);
     69         }
     70         #endregion
     71  
     72  
     73         #region 卸载系列函数
     74          
     75          76      ///<summary>
     77         /// 卸载资源包和依赖包
     78         /// </summary>
     79  
     80         /// <param name="assetBundleName">Asset bundle name.</param>
     81         public static void UnloadAssetBundle(string assetBundleName)
     82         {
     83             UnloadAssetBundleInternal (assetBundleName);
     84             UnloadDependencies (assetBundleName);
     85         }
     86         internal static void UnloadDependencies(string assetBundleName)
     87         {
     88             string[] dependencies = null;
     89             //获取所有的依赖包名称
     90             if (!MrCAssetCache.DependCache.TryGetValue(assetBundleName, out dependencies) )
     91                 return;
     92              
     93             //卸载依赖包
     94             foreach(var dependency in dependencies)
     95             {
     96                 UnloadAssetBundleInternal(dependency);
     97             }
     98             //删除依赖缓存策略
     99             MrCAssetCache.DependCache.Remove(assetBundleName);
    100         }
    101          
    102         internal static void UnloadAssetBundleInternal(string assetBundleName)
    103         {
    104             MrCAssetBundle bundle;
    105             MrCAssetCache.BundleCache.TryGetValue(assetBundleName,out bundle);
    106  
    107             if (bundle == null)
    108             {
    109                 return;
    110             }
    111             bundle.Release ();
    112         }
    113         #endregion
    114  
    115         #region GetFunction
    116         internal static WWW GetWWWCache(string key)
    117         {
    118             WWW www;
    119              
    120             MrCAssetCache.WwwCache.TryGetValue(key,out www);
    121              
    122             return www;
    123         }
    124         internal static void SetWWWCache(string key,WWW value)
    125         {
    126             MrCAssetCache.WwwCache.Add(key,value);
    127         }
    128          
    129         internal static MrCAssetBundle GetBundleCache(string key)
    130         {
    131             MrCAssetBundle ab;
    132              
    133             MrCAssetCache.BundleCache.TryGetValue(key,out ab);
    134              
    135             return ab;
    136         }
    137         internal static void SetBundleCache(string key,MrCAssetBundle value)
    138         {
    139             MrCAssetCache.BundleCache.Add(key,value);
    140         }
    141  
    142         internal static string[] GetDependCache(string key)
    143         {
    144             string[] depends;
    145              
    146             MrCAssetCache.DependCache.TryGetValue(key,out depends);
    147              
    148             return depends;
    149         }
    150         internal static void SetDependCache(string key,string[] value)
    151         {
    152             MrCAssetCache.DependCache.Add(key,value);
    153         }
    154  
    155         internal static string GetErrorCache(string key)
    156         {
    157             string error;
    158              
    159             MrCAssetCache.ErrorCache.TryGetValue(key,out error);
    160              
    161             return error;
    162         }
    163         internal static void SetErrorCache(string key,string value)
    164         {
    165             MrCAssetCache.ErrorCache.Add(key,value);
    166         }
    167         #endregion
    168  
    169         internal static void FreeBundle(string key)
    170         {
    171             MrCAssetCache.BundleCache.Remove(key);
    172         }
    173  
    174         #region Update
    175  
    176         internal static void Update()
    177         {
    178             // Collect all the finished WWWs.
    179             var keysToRemove = new List<string>();
    180             foreach (var keyValue in MrCAssetCache.WwwCache)
    181             {
    182                 WWW download = keyValue.Value;
    183                 string m_bundleName = keyValue.Key;
    184                  
    185                 // 下载失败
    186                 if (download.error != null)
    187                 {
    188                     MrCAssetCache.ErrorCache.Add(m_bundleName, download.error);
    189                      
    190                     keysToRemove.Add(m_bundleName);
    191                      
    192                     continue;
    193                 }
    194                  
    195                 // 下载成功
    196                 if(download.isDone)
    197                 {
    198                      
    199                     MrCAssetCache.BundleCache.Add(m_bundleName, new MrCAssetBundle(download.assetBundle,m_bundleName));
    200                      
    201                     keysToRemove.Add(m_bundleName);
    202                 }
    203             }
    204              
    205             // 删除下载成功的WWW对象
    206             foreach( var key in keysToRemove)
    207             {
    208                 WWW download = MrCAssetCache.WwwCache[key];
    209                  
    210                 MrCAssetCache.WwwCache.Remove(key);
    211                  
    212                 download.Dispose();
    213             }
    214         }
    215  
    216         #endregion
    217     }
    218 }

    加载包裹中的场景:
    新建一个场景,创建TestScript脚本,放到摄像机上。

     1 using UnityEngine;
     2 using System.Collections;
     3 //引入框架
     4 using MrCAssetFramework;
     5  
     6 public class TestScript : MonoBehaviour {
     7      
     8     /// <summary>
     9     /// 加载场景资源函数
    10     /// </summary>
    11     protected IEnumerator Load (string assetBundleName, string level)
    12     {
    13         IEnumerator b = da.LoadLevelAsync(assetBundleName, level, false);
    14         yield return StartCoroutine(b);
    15         Application.LoadLevel(level);
    16     }
    17  
    18     MrCAssetManager da;
    19     void Start () 
    20     {
    21         //指定统一资源标志符
    22         MrCAssetManager.URI = "http://....../UnityFiles/AssetBundlesForBlog/";
    23         //主配置文件
    24         MrCAssetManager.ManifestName = "Others";
    25         //加载成功后的操作代理
    26         MrCAssetManager.InitBlock = ((bool bundleObj) => {
    27             if (bundleObj) {
    28                 //协程操作加载的AssetBundle包裹
    29                 StartCoroutine (Load ("scenes/loaderscene.unity3d", "LoaderScene"));
    30             }
    31         });
    32         //开始我们的一切
    33         da = MrCAssetManager.DefaultAssetManager;
    34     }
    35 }

    加载包裹中的游戏对象等资源到场景中:
    在上面的测试脚本中,修改部分代码。

     1    /// <summary>
     2     /// 加载游戏对象资源函数
     3     /// </summary>
     4     protected IEnumerator LoadObj(string assetBundleName, string obj)
     5     {
     6         IEnumerator b = da.LoadAssetAsync(assetBundleName, obj, typeof(GameObject));
     7         yield return StartCoroutine(b);
     8         GameObject go = da.GetAsset<GameObject>(assetBundleName, obj);
     9         GameObject.Instantiate(go);
    10     }
    11 //-------------------------------------------------------------------------------
    12         //加载成功后的操作代理
    13         MrCAssetManager.InitBlock = ((bool bundleObj) => {
    14             if (bundleObj) {
    15                 //协程操作加载的游戏对象包裹
    16                 StartCoroutine(LoadObj("prefabs/cube.prefab", "MyCube"));
    17             }
    18         });
  • 相关阅读:
    servlet-servletConfig
    servlet-servletContext网站计数器
    servlet-cookie
    Android 无cp命令 mv引起cross-device link
    android使用mount挂载/system/app为读写权限,删除或替换系统应用
    android使用百度地图、定位SDK实现地图和定位功能!(最新、可用+吐槽)
    解决android sdk manager无法下载SDK 的问题
    Android APK反编译详解(附图)
    Android如何防止apk程序被反编译
    不用外部JAR包,自己实现JSP文件上传!
  • 原文地址:https://www.cnblogs.com/zhenlong/p/4859364.html
Copyright © 2011-2022 走看看