Unity5系列资源管理AssetBundle——加载
上次我们进行了AssetBundle打包,现在我们还把打包的资源加载到我们的游戏中。
在加载之前,我们需要把打包好的Bundle包裹放到服务器上,如果没有,也可以使用XAMPP搭建本地服务器。
加载的AssetBundle文件是放在内存中的,所以如果没有很好的管理,会使游戏性能大打折扣,因此,我们在这里最好使用缓存策略。
我们的AssetBundle:
using System;
using UnityEngine; namespace MrCAssetFramework
{
public sealed class MrCAssetBundle
{
internal AssetBundle m_AssetBundle;
internal string m_AssetBundleName;
internal MrCAssetBundle(AssetBundle assetBundle,string name)
{
this.m_AssetBundle = assetBundle;
this.m_AssetBundleName = name;
this.m_ReferencedCount = ;
} #region ReferenceCountManage
//yinyongjishujizhi
private int m_ReferencedCount;
public void Retain()
{
this.m_ReferencedCount++;
}
public void Release(){
this.m_ReferencedCount--;
//当引用计数为0时,卸载资源
if (this.m_ReferencedCount == )
{
this.m_AssetBundle.Unload (true);
MrCAssetCache.FreeBundle(this.m_AssetBundleName);
}
} public int RetainCount()
{
return this.m_ReferencedCount;
}
#endregion }
}
AssetBundle管理:
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic; namespace MrCAssetFramework
{
public class MrCAssetManager:MonoBehaviour
{ #region Singleton
private static GameObject s_go_MrCAssetManager = null;
private static MrCAssetManager s_MrCAssetManager = null; public static MrCAssetManager DefaultAssetManager{
get{
if (s_MrCAssetManager == null) {
s_go_MrCAssetManager = new GameObject ("LOAssetManager");
s_MrCAssetManager = s_go_MrCAssetManager.AddComponent<MrCAssetManager> ();
} return s_MrCAssetManager;
}
} #endregion public static string URI{ set; get;}
public static string ManifestName{ set; get;}
//无返回值泛型委托..
public static Action<bool> InitBlock; public AssetBundleManifest manifest{ set; get;} ///<summary>
/// To get the asset..
/// </summary> /// <returns>The asset..</returns>
public T GetAsset<T>(string assetbundlename,string assetname) where T:UnityEngine.Object
{
MrCAssetBundle lab = MrCAssetCache.GetBundleCache(assetbundlename); if (lab == null) {
return null;
}
else
{
return lab.m_AssetBundle.LoadAsset<T>(assetname);
}
} IEnumerator LoadManifestBundle()
{
//缓存中已经存在请求的bundle,中止..
if (MrCAssetCache.InCache(MrCAssetManager.ManifestName)) {
yield break;
} // 通过网络下载AssetBundle
WWW www = IsLoadAssetBundleAtInternal(MrCAssetManager.ManifestName);
yield return www; this.manifest = this.GetAsset<AssetBundleManifest>(MrCAssetManager.ManifestName,"AssetBundleManifest");
MrCAssetManager.InitBlock (this.manifest != null);
}
void Start()
{
StartCoroutine ("LoadManifestBundle");
} #region 加载包裹系列函数 ///<summary>
/// 检查是否已经从网络下载
/// </summary> protected WWW IsLoadAssetBundleAtInternal (string assetBundleName)
{
//已经存在了呀
MrCAssetBundle bundle = MrCAssetCache.GetBundleCache(assetBundleName);
if (bundle != null)
{
//保留数加一次
bundle.Retain ();
return null;
} //如果WWW缓存策略中包含有对应的关键字,则返回true
if (MrCAssetCache.InCache (assetBundleName)) {
return null;
} //创建下载链接
WWW www = new WWW(MrCAssetManager.URI + assetBundleName);
// 按版本号,按需要通过网络下载AssetBundle,一般在正式游戏版本中,不使用上面的,因为它会每次打开游戏重新下载
//WWW www = WWW.LoadFromCacheOrDownload(LOAssetManager.URI + assetBundleName, nowVersion); //加入缓存策略
MrCAssetCache.SetWWWCache(assetBundleName,www); return www;
} IEnumerator LoadDependencies(string assetBundleName)
{
if (this.manifest == null) {
yield return null;
}
// 获取依赖包裹
string[] dependencies = this.manifest.GetAllDependencies(assetBundleName); Debug.Log(dependencies.Length); if (dependencies.Length == )
{
yield return null;
} // 记录并且加载所有的依赖包裹
MrCAssetCache.SetDependCache(assetBundleName, dependencies); for (int i = ; i < dependencies.Length; i++)
{
yield return IsLoadAssetBundleAtInternal (dependencies [i]);
}
} 136 /// <summary>
/// 加载资源包
/// </summary> IEnumerator LoadAssetBundle(string assetBundleName)
{
if (MrCAssetCache.InCache(assetBundleName)) {
yield break;
}
// 通过网络下载AssetBundle
WWW www = IsLoadAssetBundleAtInternal(assetBundleName);
yield return www; // 通过网络加载失败,下载依赖包裹
yield return StartCoroutine(LoadDependencies(assetBundleName));
} ///<summary>
/// 异步加载资源
/// </summary> public IEnumerator LoadAssetAsync (string assetBundleName, string assetName, System.Type type)
{
//开始加载包裹
yield return StartCoroutine(LoadAssetBundle (assetBundleName));
} ///<summary>
/// 异步加载场景
/// </summary> public IEnumerator LoadLevelAsync (string assetBundleName, string levelName, bool isAdditive)
{
//加载资源包
yield return StartCoroutine(LoadAssetBundle (assetBundleName)); }
#endregion #region Update void Update()
{
MrCAssetCache.Update();
}
#endregion
}
}
缓存管理:
using System;
using System.Collections.Generic;
using UnityEngine; namespace MrCAssetFramework
{
internal sealed class MrCAssetCache
{
#region 包裹缓存机制
//创建缓存字典
private static Dictionary<string, MrCAssetBundle> assetBundleCache;
//缓存字典属性
private static Dictionary<string, MrCAssetBundle> BundleCache
{
get{
if (assetBundleCache == null) {
assetBundleCache = new Dictionary<string, MrCAssetBundle> ();
} return assetBundleCache;
}
} //创建缓存WWW对象
private static Dictionary<string, WWW> wwwCache;
//创建缓存WWW对象属性
private static Dictionary<string, WWW> WwwCache{
get{
if (wwwCache == null) {
wwwCache = new Dictionary<string, WWW> ();
} return wwwCache;
}
}
//创建依赖缓存对象
private static Dictionary<string, string[]> dependCache;
//创建依赖缓存属性
private static Dictionary<string, string[]> DependCache
{
get{
if (dependCache == null) {
dependCache = new Dictionary<string, string[]> ();
}
return dependCache;
}
} private static Dictionary<string, string> errorCache;
private static Dictionary<string,string> ErrorCache{
get{
if (errorCache == null) {
errorCache = new Dictionary<string, string> ();
}
return errorCache;
}
} ///<summary>
/// Instantiate the cache.
/// </summary> /// <returns><c>true</c>, if cache was ined, <c>false</c> otherwise.</returns>
/// <param name="assetbundlename">Assetbundlename.</param>
internal static bool InCache(string assetbundlename)
{
return MrCAssetCache.BundleCache.ContainsKey(assetbundlename);
}
#endregion #region 卸载系列函数 ///<summary>
/// 卸载资源包和依赖包
/// </summary> /// <param name="assetBundleName">Asset bundle name.</param>
public static void UnloadAssetBundle(string assetBundleName)
{
UnloadAssetBundleInternal (assetBundleName);
UnloadDependencies (assetBundleName);
}
internal static void UnloadDependencies(string assetBundleName)
{
string[] dependencies = null;
//获取所有的依赖包名称
if (!MrCAssetCache.DependCache.TryGetValue(assetBundleName, out dependencies) )
return; //卸载依赖包
foreach(var dependency in dependencies)
{
UnloadAssetBundleInternal(dependency);
}
//删除依赖缓存策略
MrCAssetCache.DependCache.Remove(assetBundleName);
} internal static void UnloadAssetBundleInternal(string assetBundleName)
{
MrCAssetBundle bundle;
MrCAssetCache.BundleCache.TryGetValue(assetBundleName,out bundle); if (bundle == null)
{
return;
}
bundle.Release ();
}
#endregion #region GetFunction
internal static WWW GetWWWCache(string key)
{
WWW www; MrCAssetCache.WwwCache.TryGetValue(key,out www); return www;
}
internal static void SetWWWCache(string key,WWW value)
{
MrCAssetCache.WwwCache.Add(key,value);
} internal static MrCAssetBundle GetBundleCache(string key)
{
MrCAssetBundle ab; MrCAssetCache.BundleCache.TryGetValue(key,out ab); return ab;
}
internal static void SetBundleCache(string key,MrCAssetBundle value)
{
MrCAssetCache.BundleCache.Add(key,value);
} internal static string[] GetDependCache(string key)
{
string[] depends; MrCAssetCache.DependCache.TryGetValue(key,out depends); return depends;
}
internal static void SetDependCache(string key,string[] value)
{
MrCAssetCache.DependCache.Add(key,value);
} internal static string GetErrorCache(string key)
{
string error; MrCAssetCache.ErrorCache.TryGetValue(key,out error); return error;
}
internal static void SetErrorCache(string key,string value)
{
MrCAssetCache.ErrorCache.Add(key,value);
}
#endregion internal static void FreeBundle(string key)
{
MrCAssetCache.BundleCache.Remove(key);
} #region Update internal static void Update()
{
// Collect all the finished WWWs.
var keysToRemove = new List<string>();
foreach (var keyValue in MrCAssetCache.WwwCache)
{
WWW download = keyValue.Value;
string m_bundleName = keyValue.Key; // 下载失败
if (download.error != null)
{
MrCAssetCache.ErrorCache.Add(m_bundleName, download.error); keysToRemove.Add(m_bundleName); continue;
} // 下载成功
if(download.isDone)
{ MrCAssetCache.BundleCache.Add(m_bundleName, new MrCAssetBundle(download.assetBundle,m_bundleName)); keysToRemove.Add(m_bundleName);
}
} // 删除下载成功的WWW对象
foreach( var key in keysToRemove)
{
WWW download = MrCAssetCache.WwwCache[key]; MrCAssetCache.WwwCache.Remove(key); download.Dispose();
}
} #endregion
}
}
加载包裹中的场景:
新建一个场景,创建TestScript脚本,放到摄像机上。
using UnityEngine;
using System.Collections;
//引入框架
using MrCAssetFramework; public class TestScript : MonoBehaviour { /// <summary>
/// 加载场景资源函数
/// </summary>
protected IEnumerator Load (string assetBundleName, string level)
{
IEnumerator b = da.LoadLevelAsync(assetBundleName, level, false);
yield return StartCoroutine(b);
Application.LoadLevel(level);
} MrCAssetManager da;
void Start ()
{
//指定统一资源标志符
MrCAssetManager.URI = "http://....../UnityFiles/AssetBundlesForBlog/";
//主配置文件
MrCAssetManager.ManifestName = "Others";
//加载成功后的操作代理
MrCAssetManager.InitBlock = ((bool bundleObj) => {
if (bundleObj) {
//协程操作加载的AssetBundle包裹
StartCoroutine (Load ("scenes/loaderscene.unity3d", "LoaderScene"));
}
});
//开始我们的一切
da = MrCAssetManager.DefaultAssetManager;
}
}
加载包裹中的游戏对象等资源到场景中:
在上面的测试脚本中,修改部分代码。
/// <summary>
/// 加载游戏对象资源函数
/// </summary>
protected IEnumerator LoadObj(string assetBundleName, string obj)
{
IEnumerator b = da.LoadAssetAsync(assetBundleName, obj, typeof(GameObject));
yield return StartCoroutine(b);
GameObject go = da.GetAsset<GameObject>(assetBundleName, obj);
GameObject.Instantiate(go);
}
//-------------------------------------------------------------------------------
//加载成功后的操作代理
MrCAssetManager.InitBlock = ((bool bundleObj) => {
if (bundleObj) {
//协程操作加载的游戏对象包裹
StartCoroutine(LoadObj("prefabs/cube.prefab", "MyCube"));
}
});
Unity5系列资源管理AssetBundle——加载的更多相关文章
- Unity5.x版本AssetBundle加载研究
之前说了 “Unity5.x版本AssetBundle打包研究”,没看过的请先看一下:http://www.shihuanjue.com/?p=57 再来看本文,有一定的连接性. 先梳理一下思路: 要 ...
- Unity5系列资源管理AssetBundle——更新实现
前面我们研究了AssetBundle的打包与加载,现在我们来了解下如何在项目中根据版本号更新内容. 最最重要的一点,细心的朋友应该看到了在加载AssetBundle的MrcAssetManager类中 ...
- Unity5系列资源管理AssetBundle——打包
资源管理是游戏开发的重要环节,Unity中使用AssetBundle可以非常方便地帮我们打包和更新游戏内容,在5系列中,AssetBundle更是方便好用,现在让我们先进行打包吧. 刚说了,5系列打包 ...
- AssetBundle加载API
AssetBundle加载API 在Unity 5当中,可以通过4个不同的API来加载AssetBundle,4个API可以用两个条件来区分: AssetBundle是 LZMA压缩. LZ4压缩还是 ...
- 老调重弹:JDBC系列之<驱动加载原理全面解析) ----转
最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者 ...
- RX系列四 | RxAndroid | 加载图片 | 提交表单
RX系列四 | RxAndroid | 加载图片 | 提交表单 说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较 ...
- 【iOS系列】-UIWebView加载网页禁止左右滑动
[iOS系列]-UIWebView加载网页禁止左右滑动 问题: 做项目时候,用UIWebView加载网页的时候,要求是和微信网页中打开的网页的效果一样,也即是只能上下滑动,不能左右滑动,也不能缩放. ...
- SpringBoot系列之配置文件加载位置
SpringBoot系列之配置文件加载位置 SpringBoot启动会自动扫描如下位置的application.properties或者application.yml文件作为Springboot的默认 ...
- AssetBundle系列——资源的加载、简易的资源管理器
每个需要进行资源管理的类都继承自IAssetManager,该类维护它所使用到的所有资源的一个资源列表.并且每个资源管理类可以重写其资源引用接口和解引用接口. 每个管理器有自己的管理策略,比如Scen ...
随机推荐
- [Q]自定义快捷键
打开CAD批量打图精灵主界面可以使用以下三个命令其一:“QuickPlot”.“QPlot”.“QP”.“PP”,其中“PP”可以更改, 方法如下:进入AutoCAD传统界面,点“工具”-“自定义”- ...
- win8 or win7安装ubuntu双系统
安装双系统的效果 现在使用win和linux双系统,整个环境相当方便好用,比如在Linux系统上,仍能访问NTFS(win的文件系统格式)中的文件和文档,当然win下的一些像matlab.vs等是不能 ...
- 8个不可不知的Mac OS X专用命令行工具【转】
OS X的终端下通用很多Unix的工具和脚本.如果从Linux迁移到OS X会发现很多熟悉的命令和脚本工具,其实并没有任何区别. 但是OS X也提供了很多其他系统所没有的特别的命令行工具.我们推荐8个 ...
- C#中(int)a和Convert.ToInt32(a)的区别
首先,在 C# 中,int 其实就是 System.Int32,即都是32位的. 其次,(int) 和 Convert.ToInt32 是两个不同的概念,前者是类型转换,而后者则是内容转换,它们并不总 ...
- 将递归函数非递归化的一般方法(cont)
本文通过模拟汇编里的stack机制,构建一个自己的stack,然后将上一篇blog末尾的递归函数void bst_walk(bst_node_t *root)非递归化. o libstack.h #i ...
- gulp 安装步骤
第一步:安装node 搭建node环境:进入官网 http://nodejs.org ,然后点击的绿色的 install 按钮,下载完成后直接运行程序. 第二步:使用命令行 (1)输入指令:node ...
- zabbix 布署实践【3 proxy安装】
使用openstack在生产环境创建的一台虚拟机 环境 CentOS7 4核4G内存40G硬盘 IP:10.120.150.150 镜像默认关闭防火墙,selinux ,NetworkManage ...
- PAT乙级1004. 成绩排名 (20)
读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3行:第2个学生 ...
- 斗地主 (NOIP2015 Day1 T3)
斗地主 张牌,因为它可以连在K后, 总体思路为 先出炸弹和四带二 再出三带一 再把对牌和单牌出完 记录并更新Answer,后枚举顺子,并继续向下搜索. 注意:弄明白题意,题目描述不太清楚....另外, ...
- 使用recordmydesktop进行屏幕录像
屏幕录像的功能对于分享游戏攻略.演示电脑软件的操作是必不可少的.在Windows下可能一般的用户就下载盗版的商业软件来做了.而在GNU/Linux操作系统下,则有现成的自由软件可供使用,只不过没有图形 ...