AssetBundle使用心得【资源加载】
0.资源加载方式
- 静态资源 Asset下所有资源称为静态资源
- Resources资源 Resources目录下,通过实例化得到的资源
- AssetBundle资源 又称为增量更新资源
1.什么是AssetBundle包(下面称为AB包)
一种存放在硬盘上压缩文件组形式,包含序列化文件(Manifest)与资源文件(Resources)。压缩包的压缩算法包括LZMA(流式压缩)与LZ4(块压缩)算法,前者压缩比例更高解压耗时更大。
PS:www使用后是需要销毁的!!!www.Dispose();
2.AB包打包原则有哪些
- 引用同意贴图、材质、模型的资源最好一起打包
- 一起展示的部分最好一起打包,比如一个场景,一个面板等
- 导出目录一定要存在,不存在导出会失败
- 加载资源时请务必清空一次缓存区!!重要!重要!
3.AB场景资源打包
- 打包前把需要的shader放到Edit/ProjectSetting/Graphics 的Always Includes Shaders上,不然加载后会出现shader关联不上的问题
方式1.场景打包方式0 (打成多个资源包)
- 设置要打包的场景资源
- Editor中导入如下代码
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO; public class ABSceneAll
{
[MenuItem("Custom Editor/Version1CreateAB")]
static void CreateSceneVersion1()
{
//清空一下缓存
Caching.CleanCache(); //路径
string outPath = Application.streamingAssetsPath + "/AssetBundle";
if (!Directory.Exists(outPath))
{
Directory.CreateDirectory(outPath);
} //检测所有的AB包资源创建Manifest文件 这里选择的是不进行任何特殊要求
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(outPath, BuildAssetBundleOptions.None, BuildTarget.Android); //存储txt文件
if (manifest != null)
{
string txtPath = Application.streamingAssetsPath + "/AssetBundle" + "/gamehall.txt";
string manifestPath = Application.streamingAssetsPath + "/AssetBundle" + "/AssetBundle.assetbundle";
string temp = ""; //得到所有的需要打AB包的资源名
string[] assetBundleNames = manifest.GetAllAssetBundles(); //提示信息 & 安全校验
if (assetBundleNames.Length != )
{
EditorUtility.DisplayDialog("错误提示", "这是个安全校验,表示已经出问题了打包的场景过多", "确定");
return;
} for (int i = ; i < assetBundleNames.Length; i++)
{
temp += assetBundleNames[i] + ":" + manifest.GetAssetBundleHash(assetBundleNames[i]).ToString() + "\r\n";
}
temp += "前二十位:" + manifest.GetAssetBundleHash(assetBundleNames[]).ToString().Substring(, ) + manifest.GetAssetBundleHash(assetBundleNames[]).ToString().Substring(, ); FileStream fs = new FileStream(txtPath, FileMode.OpenOrCreate, FileAccess.Write);//创建写入文件
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(temp);//开始写入值
sw.Close();
fs.Close();
} //资源刷新
AssetDatabase.Refresh();
}
}
- Custom Editor中选择对应选项进行打包(这里打出来的包就包含了Manifest文件,2个不同的AB文件)
- 读取方式如下代码
/***************************************
Editor: Tason
Version: v1.0
Last Edit Date: 2018-XX-XX
Tel: 328791554@qq.com
Function Doc: ***************************************/ using UnityEngine;
using System.Collections; public class MyTest : MonoBehaviour
{
void Awake()
{ StartCoroutine(LoadScene());
} private IEnumerator LoadScene()
{
Caching.CleanCache();
//加载多个文件 Manifest + AssetBundle资源
WWW downManifest = WWW.LoadFromCacheOrDownload("file://" + Application.streamingAssetsPath + "/AssetBundle" + "/AssetBundle", );
//加载时间 600 * 0.1s 最长加载60s
for (int i = ; i < ; i++)
{
if (downManifest.isDone)
{
break;
}
if (i % == )
Debug.Log("加载进度:" + downManifest.progress.ToString("#0.00"));
yield return new WaitForSeconds(0.1f);
}
if (downManifest.isDone)
Debug.Log("文件目录加载成功 ----- √");
else
{
Debug.Log("文件目录加载失败 ----- X");
yield break;
} AssetBundleManifest abm = downManifest.assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] abResourcesNames = abm.GetAllAssetBundles();
for (int i = ; i < abResourcesNames.Length; ++i)
{
WWW downResource = WWW.LoadFromCacheOrDownload("file://" + Application.streamingAssetsPath + "/AssetBundle" + '/' + abResourcesNames[i], );
for (int n = ; n < ; n++)
{
if (downResource.isDone)
{
break;
}
if (i % == )
Debug.Log("加载进度:" + downManifest.progress.ToString("#0.00"));
yield return new WaitForSeconds(0.1f);
}
if (downResource.isDone)
Debug.Log(string.Format("文件[{0}]加载成功 ----- √", i));
else
{
Debug.Log(string.Format("文件[{0}]加载失败 ----- X", i));
yield break;
} } Application.LoadLevel("S1"); yield return null; }
}
方式2.场景打包方式1(打成1个资源包)
- 设置要打包的场景资源
- Editor中导入如下代码
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO; public class ABSceneAll
{
[MenuItem("Custom Editor/Version0CreateAB")]
static void CreateSceneVersion0()
{
//清空一下缓存
Caching.CleanCache(); //路径
string outPath = Application.streamingAssetsPath + "/AssetBundle";
if (!Directory.Exists(outPath))
{
Directory.CreateDirectory(outPath);
} string TtargetPath = outPath + "/MY01.AB";
string[] Scenes = { "Assets/Scene/S0.unity","Assets/Scene/S1.unity" }; //打包场景
BuildPipeline.BuildPlayer(Scenes, TtargetPath, BuildTarget.Android, BuildOptions.BuildAdditionalStreamedScenes); //资源刷新
AssetDatabase.Refresh();
}
}
- Custom Editor中选择第一个选项进行打包(这里打出来的包就是一个AB文件)
- 读取方式如下代码
/***************************************
Editor: Tason
Version: v1.0
Last Edit Date: 2018-XX-XX
Tel: 328791554@qq.com
Function Doc: ***************************************/ using UnityEngine;
using System.Collections; public class MyTest : MonoBehaviour
{
void Awake()
{ StartCoroutine(LoadScene());
} private IEnumerator LoadScene()
{
Caching.CleanCache();
//资源加载 对应单一资源
WWW download = WWW.LoadFromCacheOrDownload("file://" + Application.streamingAssetsPath + "/AssetBundle" + "/MY01.AB", );
yield return download;
Application.LoadLevel("S1");
download.Dispose(); yield return null; }
}
AB包卸载
1.减少内存消耗
2.可能导致丢失的情况
AssetBundle.Unload(bool _b); ----- 这里不是静态函数,前面要写获得的AB包对象
True: 强制卸载,不管有没有引用
False:卸载没有用的资源
踩坑
- AssetBunlde不区分大小写 所以建议全部用小写
- Resources和AssetBundle路径不同,Resources是相对路径,AssetBundle都有
- 依赖关系一定要处理好,不然包体会很大
- AssetBundle.CreateFromFile不能加载压缩过的AssetBundle,需要用www加载?!
- 资源间的关系必须是强关联,不能有资源通过代码里面的“Resources.Load<Type>”“Shader.Find”等弱关联连接,因为它不会被打包进AB包(已测试,非常关键)
- 如果你要把资源包放在StreamingAssets目录下进行资源加载,注意三端的路径是不一样的(这就很虚浮!)
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
string finalPath = "file://" + Application.dataPath + "/StreamingAssets";
#elif UNITY_ANDROID
string finalPath = "jar:file://" + Application.dataPath + "!/assets";
#elif UNITY_IPHONE
string finalPath = Application.dataPath + "/Raw"
#endif
Shader&AB包的关系!
1.首先场景中关联了材质的shader是会被打包到AB包中的(如果没打包进去,就去菜单栏 Edit -----> ProjectSetting ----> Graphics -----> Always Included Shaders 中进行添加)
EG:后面我又做了个实验,通过AssetBundleBrower检查过一次,发现确实打包进去了,但UITexture的Shader还是存在问题,使用上需要格外小心,最好还是给引用的地方放一份Shader,ε=(´ο`*)))很是无奈啊!!!!
2.但是存在一些问题,比如加载AB的场景可能会存在“关联丢失”的问题,表现出来的方式就像是shader没有被打包,但是当你重新点选同样的shader后又恢复了!这就很坑爹,原因不明
3.那么如何解决这个问题呢,我参考了网上的一个方法,测试成功表示可行,在需要挂在新shader的父物体下面加上如下脚本即可,相当于它帮你记录了关联,然后运行时重新关联了一次!(适用于Mesh UGUI)
4.当然如果你的代码里面存在创建模型这种骚操作,上诉挂载的方式是肯定行不通的,那就需要你自己加一句代码来重新关联咯,如:“m_materials[0].shader = Shader.Find("Custom/CutLineShader");”
/***************************************
Editor: Tason
Last Edit Date: 2018-XX-XX
Tel: 328791554@qq.com
Function Doc:
在需要自定义的使用自定义shader的物体的最上层父物体上加上这个
脚本可以保证shader关联不丢失
Version: 0.0.1 测试版
***************************************/ using UnityEngine;
using System.Collections;
using System.Collections.Generic; public class ShaderBD : MonoBehaviour
{
private List<Material> thisMaterial;
private List<string> shaders; void Start()
{
thisMaterial = new List<Material>();
shaders = new List<string>(); MeshRenderer[] meshRenderer = GetComponentsInChildren<MeshRenderer>();
int length = meshRenderer.Length; for (int i = ; i < length; i++)
{
int count = meshRenderer[i].materials.Length;
for (int j = ; j < count; j++)
{
Material _mater = meshRenderer[i].materials[j];
thisMaterial.Add(_mater);
shaders.Add(_mater.shader.name);
}
} SkinnedMeshRenderer[] meshSkinRenderer = GetComponentsInChildren<SkinnedMeshRenderer>();
length = meshSkinRenderer.Length; for (int i = ; i < length; i++)
{
int count = meshSkinRenderer[i].materials.Length;
for (int j = ; j < count; j++)
{
Material _mater = meshSkinRenderer[i].materials[j];
thisMaterial.Add(_mater);
shaders.Add(_mater.shader.name);
}
} for (int i = ; i < thisMaterial.Count; i++)
{
thisMaterial[i].shader = Shader.Find(shaders[i]);
}
}
}
总结:如果需要使用AB包进行场景打包,那么NGUI上使用的Shader,需要单独放在整合包(ABLoad的项目)中,如果是UGUI或者Mesh使用Shader,请在父物体上挂载上述脚本进行关联!!!!后续持续关注
对了!下面是AssetBundleBrower(查看打包内容的UnityEditor 工具,直接导入Editor,在Window窗口中就能找到它了!支持5.6以上版本)
链接:https://pan.baidu.com/s/1BN2EofgVXIthKiAIq3JPyg 密码:mg8i
AssetBundle使用心得【资源加载】的更多相关文章
- 详谈 Unity3D AssetBundle 资源加载,结合实际项目开发实例
第一次搞资源更新方面,这里只说更新,加载,AssetBundle资源加载,谈谈自己的理解,以及自己在项目中遇到的那些神坑,现在回想一下,真的是自己跪着过来的,说多了,都是泪. 我这边是安卓AssetB ...
- Unity -- AssetBundle(本地资源加载和加载依赖关系)
1.本地资源加载 1).建立Editor文件夹 2).建立StreamingAssets文件夹和其Windows的子文件夹 将下方第一个脚本放入Editor 里面 脚本一 资源打包AssetBund ...
- Unity3D之Mecanim动画系统学习笔记(十):Mecanim动画的资源加载相关
资源加载是必备的知识点,这里就说说Mecanim动画的资源如何打包及加载. 注意,Unity4.x和Unity5.x的AssetBundle打包策略不一样,本笔记是基于Unity4.x的AssetBu ...
- Unity AssetBundle的生成、加载和热更新
当前使用的是unity2018.2.6版本. 生成AssetBundle 这个版本生成AssetBundle有两种方式,一种是在资源的Inspector面板下边配置AssetBundle名称,然后调用 ...
- Unity AssetBundle的几个加载方式
string path = @"AssetBundles/scene/cubewall.ab"; string cacheDownloadPath = @"file:// ...
- 细谈unity资源加载和卸载
转载请标明出处:http://www.cnblogs.com/zblade/ 一.概要 在了解unity的资源管理方式之后,接下来细谈一下Unity的资源是如何从磁盘中加载到运行时的内存中,以及又是如 ...
- Direct2D开发:从资源加载位图
转载请注明出处:http://www.cnblogs.com/Ray1024 一.概述 Direct2D使用Windows图像处理组件 (WIC) 来加载位图.从文件加载位图的方法很简单,而且网上的教 ...
- prelaod场景,用来显示资源加载进度
phaser.js的源码可以到它在github上的托管里去下载,游戏要用到的图片声音等素材资源请点击这里下载.Phaser的使用非常简单,只需要引入它的主文件,然后在页面中指定一个用来放置canvas ...
- 【Android开发学习笔记】【高级】【随笔】插件化——资源加载
前言 上一节我们针对插件最基本的原理进行了一个简单的demo实现,但是由于插件的Context对象被宿主所接管,因此无法加载插件程序的资源.那么如何解决这个问题捏? 有人提出这样的方案:将apk中的资 ...
随机推荐
- jsp jstl quote symbol expected
org.apache.jasper.JasperException: /WEB-INF/jsp/user/index.jsp (line: 2, column: 27) quote symbol ex ...
- Mac 日常使用tips
20180725: windows标准的键盘连接了mac如何映射键盘?最大的好处是可以向后删除,还可以一键PageUP, PageDown ref: https://support.apple.com ...
- 注解_Annotation
---恢复内容开始--- 一.什么是注解 注解,英文Annotation,它不是程序本身,是对程序的解释,在这里我会想到为什么不能使用注释呢,因为注解是关于程序对信息的处理的流程的一些说明,而且格式也 ...
- Bash常用快捷键及其作用
在 Bash 中有非常多的快捷键,如果可以熟练地使用这些快捷键,可有效地提高我们的工作效率.只是快捷键相对较多,不太好记忆,这就要多加练习和使用.这些快捷键如表 1 所示. 表 1 Bash 常用快捷 ...
- C#中EXCEL表格的内容进度条实现
public void ExportToExcel() { DataTable dt = getDataTable(); if (dt == null) { MessageBox.Show(" ...
- python 爬虫启航2.0
文章解析: 1.正则表达式解析 2.beautifulsoup,BeautifulSoup是一个复杂的树形结构,她的每一个节点都是一个python对象,获取网页的内容就是一个提取对象内容的过程,它的提 ...
- jqueryValidate
参数详情可参见: http://www.runoob.com/jquery/jquery-plugin-validate.html 基本使用: /** 数据保存前校验 **/ $("#use ...
- Android Studio 3.1.3正式版的新坑。。。
Gradle编译时没问题,运行App时候出现: java.util.NoSuchElementException java.lang.RuntimeException: com.android.bui ...
- 在delphi中XLSReadWriteII.组件的应用实例(1)
第三方组件:XLSReadWriteII.v.5.20.67_XE3 实例源码如下: unit Unit1; interface uses Winapi.Windows, Winapi.Message ...
- chrome不能浏览任何网页,提示配置proxy,Ubuntu
自从在Ubuntu安装virtualbox以后,我的chrome浏览器就不能上网了,提示我检查proxy信息, 后面设置了noproxy就ok啦. 不用使用命令,一次设置,终身有效. 首先,安装gks ...