Assetbundle2
Assetbundle可以将Prefab封装起来,这是多么方便啊! 而且我也强烈建议大家将Prefab封装成Assetbundle,因为Prefab可以将游戏对象身上带的游戏游戏组件、游戏脚本、材质都封装在一起。当从服务器上将Assetbundle下载以后直接Instantiate就可以放入游戏中。
无论是模型资源还是UI资源,最好是先把他们放在Prefab中,然后在做成Assetbundle
如果打包场景的话那么内存与size就是 公用模型的size * N个场景,想想其实挺恐怖的。其实我们可以巧妙的使用,首先把场景中公用的部分和私有的部分统统放入Unity, 然后烘培整个场景。 当场景烘培完毕后把公用的模型部分在拿出去,场景只只保留私有的模型。还可以做一个工具将公用模型在场景中的坐标保存在XML中(每个场景文件会对应一个公用模型的XML信息),最后在将公用的模型分别封装在别的Assetbundle中。
服务器上提供每个场景的Assetbundle ,和公用模型的Assetbundle,一般公用模型的Assetbundle可以放在常驻内存中(可能使用频繁、根据项目的不同而定)场景Assetbundle下载完毕后,现载入场景然后在根据场景对应的XML信息将公用模型部分动态的在添加到场景中,这样就完成了一个场景的构建。
Prefab打包技巧: Prefab打包时自身是不占多少空间的 <=1KB 但是Prefab上是可以关联 这五大部分 “界面,模型,特效,声音,场景,脚本”以及在Hierarchy视图中 坐标/缩放/旋转。 关联这些信息以后就会很大,所以为了避免资源的浪费尽量避免Prefab重复关联。
一个prefab下面可以同时关联多个游戏对象 ,这里举个例子如果你的 Prefab下面放了一个模型 它的大小可能是500k ,在 Prefab下面放了十个完全相同模型 它的大小可能是501k 。 如果Prefab下面放了两个不同的模型,它的大小可能就会是 500k x 2 的size ,也就是说Prefab与关联的数量是无关的 。
加密部分: assetbundle 是可以转换成 字节数组 ,客户端与服务器约定一组解密 字节数组的算法就可以实现资源加密。
1、相同的模型尽量打包在一起,他们会公用一套资源文件。
2、相同模型具有不同的脚本、组件的话把他们放在不同的Prefab中,最后把这些Prefab一起打包在一个Assetbundle中
3、不相同的模型尽量分开打包
对在Project视图中选中的对象进行分开打包:
[MenuItem("Custom Editor/Create AssetBunldes Main")]
static void CreateAssetBunldesMain()
{
//获取在Project视图中选择的所有游戏对象
Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
//遍历所有的游戏对象
foreach (Object obj in SelectedAsset)
{
string sourcePath = AssetDatabase.GetAssetPath(obj);
//本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径
//StreamingAssets是只读路径,不能写入
//服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。
string path = CreatePath();
string targetPath = path + obj.name + ".assetbundle";
if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies))
{
Debug.Log(obj.name + "资源打包成功");
}
else
{
Debug.Log(obj.name + "资源打包失败");
}
}
//刷新编辑器
AssetDatabase.Refresh();
}
对在Project视图中选中的对象进行统一打包,打包成一个AB:
[MenuItem("Custom Editor/Create AssetBunldes ALL")]
static void CreateAssetBunldesALL()
{
Caching.CleanCache();
string path = CreatePath();
string Path = path + "ALL.assetbundle";
Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
//这里注意第二个参数就行
if (BuildPipeline.BuildAssetBundle(null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies))
{
AssetDatabase.Refresh();
}
else
{
}
}
private static string CreatePath()
{
string path = Application.dataPath + "/StreamingAssets/";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)
参数1:它只能放一个对象,因为我们这里是分别打包,所以通过循环将每个对象分别放在了这里。
参数2:可以放入一个数组对象。
默认情况下打的包只能在电脑上用,如果要在手机上用就要添加一个参数。
Android上:BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.Android)
IOS上:BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.iPhone)
另外,电脑上和手机上打出来的Assetbundle不能混用,不同平台只能用自己的。
读取Assetbundle
然后我们来学习如何运行时读取Assetbundle,Assetbundle是可以同时放在服务器或者本地的,无论放在哪里两种下载读取的方式是完全一样的
//不同平台下StreamingAssets的路径是不同的,这里需要注意一下。
public static readonly string PathURL =
#if UNITY_ANDROID
"jar:file://" + Application.dataPath + "!/assets/";
#elif UNITY_IPHONE
Application.dataPath + "/Raw/";
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
"file://" + Application.dataPath + "/StreamingAssets/";
#else
string.Empty;
#endif void OnGUI()
{
//读取一个资源
if (GUILayout.Button("Main Assetbundle"))
{
StartCoroutine(LoadMainGameObject(PathURL + "Cube1.assetbundle"));
StartCoroutine(LoadMainGameObject(PathURL + "Cube2.assetbundle"));
}
//读取全部资源
if (GUILayout.Button("ALL Assetbundle"))
{
StartCoroutine(LoadALLGameObject(PathURL + "ALL.assetbundle"));
} } //读取一个资源
private IEnumerator LoadMainGameObject(string path)
{
WWW bundle = new WWW(path);
yield return bundle; //加载到游戏中 mainAsset只适用于ab里面只打包了一个对象
yield return Instantiate(bundle.assetBundle.mainAsset);
bundle.assetBundle.Unload(false);
} //读取全部资源
private IEnumerator LoadALLGameObject(string path)
{
WWW bundle = new WWW(path);
yield return bundle; //通过Prefab的名称把他们都读取出来
Object obj0 = bundle.assetBundle.Load("Cube1");
Object obj1 = bundle.assetBundle.Load("Cube2"); //加载到游戏中
yield return Instantiate(obj0);
yield return Instantiate(obj1);
bundle.assetBundle.Unload(false);
}
这里我们详细的说说 下载类WWW
WWW bundle = new WWW(path);
这样的做法是通过一个路径进行下载(无论是服务器路径还是本地路径下载操作都一样)但是bundle只能保存在内存中,也就是退出游戏在进入还得重新下,很显然在游戏中我们不能使用这种方式。
private IEnumerator LoadMainCacheGameObject(string path)
{
//如果缓存中没有此ab,就去网络上下载
WWW bundle = WWW.LoadFromCacheOrDownload(path,);
yield return bundle; //加载到游戏中
yield return Instantiate(bundle.assetBundle.mainAsset);
bundle.assetBundle.Unload(false);
}
使用的方法是WWW.LoadFromCacheOrDownload(path,5);
参数1:服务器或者本地下载地址
参数2:版本号
Unity会下载Assetbundle本地中,它的工作原理是先通过(下载地址和版本号)先在本地去找看有没有这个Assetbundle,如果有直接返回对象,如果没有的话,再根据这个下载地址重新从服务器或者本地下载。这里版本号起到了很重要的作用,举个例子,同一下载地址版本号为1的时候已经下载到本地,此时将版本号的参数改成2 那么它又会重新下载,如果还保持版本号为1那么它会从本地读取,因为本地已经有版本号为1的这个Assetbundle了。你不用担心你的资源本地下载过多,也不用自己手动删除他们,这一切的一切Unity会帮我们自动完成,它会自动删除掉下载后最不常用的Assetbundle ,如果下次需要使用的话只要提供下载地址和版本后它会重新下载。
我们再聊聊Assetbundle 中的脚本,在移动平台下Assetbundle里面放的脚本是不会被执行的,还记得我们打包前给两个Prefab挂上了脚本吗?在手机上将Assetbundle下载到本地后,加载进游戏中Prefab会自动在本地找它身上挂着的脚本,他是根据脚本的名来寻找,如果本地有这条脚本的话,Prefab会把这个脚本重新绑定在自身,并且会把打包前的参数传递进来。如果本地没有,身上挂的条脚本永远都不会被执行。
如果你的Assetbundle中的Prefab上引用的对象,那么这样做就会出错了,你需要设定他们的依赖关系。或者运行时通过脚本动态的载入对象。
http://docs.unity3d.com/Documentation/ScriptReference/BuildPipeline.PopAssetDependencies.html
http://docs.unity3d.com/Documentation/ScriptReference/BuildPipeline.PushAssetDependencies.html
像这样重新打包就可以。但是,Unity官方表示这些方法都过时了,推荐使用Unity5.0以上的资源打包API了!可以避免很多坑!
2014年10月补充
WWW.LoadFromCacheOrDownload 这个方法建议大家以后不要再用了
因为是异步方法,而且还占用内存。
强烈建议使用AssetBundle.CreateFromFile 它是一个同步方法。现在IOS 和 android 都支持了,强烈建议用。
打包的时候需要选择不压缩。
//打包场景
BuildPipeline.BuildStreamedSceneAssetBundle(levels, path, target, BuildOptions.UncompressedAssetBundle))
//打包资源
BuildPipeline.BuildAssetBundle(null, assets, path, BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies, target);
因为不压缩, 所以就需要我们自己来压缩资源了, 可以用LZMA 和 GZIP来进行压缩。
1.打包出来的Assetbundle我们自己用LZMA压缩,上传到服务器上。
2.IOS或者Android下载这些assetbundle
3.解压缩这些assetbundle并且保存在Application.persistentDataPath 目录下。
4.以后通过AssetBundle.CreatFromFile 读取assetbundle。
此法确实可行,我们已经在实际项目中轰轰烈烈的使用了。。
http://www.xuanyusong.com/archives/2405
Assetbundle2的更多相关文章
- Unity AssetBundles and Resources指引 (三) AssetBundle基础
本文内容主要翻译自下面这篇文章 https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and- ...
- Siki_Unity_3-7_AssetBundle从入门到掌握
Unity 3-7 AssetBundle从入门到掌握 任务1&2&3:课程介绍 AssetBundle -- 用于资源的更新 为了之后的xLua (Lua热更新的框架)打下基础 任务 ...
随机推荐
- SpringBoot非官方教程 | 第七篇:springboot开启声明式事务
转载请标明出处: http://blog.csdn.net/forezp/article/details/70833629 本文出自方志朋的博客 springboot开启事务很简单,只需要一个注解@T ...
- Android 初步-Android文件目录介绍
src:存放的是应用程序使用到的java文件. gen:系统自动生成的目录,不需要程序员进行修改,包含了R.java文件.该文件包含了 程序使用到的资源文件对应的唯一资源ID,注意:如果R文件生成错误 ...
- Webpack4 学习笔记八 开发环境和生产环境配置
webpack resolve属性 webpack 区分开发环境和生产环境 webpack resolve属性 该选项的作用是设置模块如何被解析. resolve.alias: 设置别名, 在vue中 ...
- Integer大小比较问题
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer ...
- HTTP基本内容
*********************HTTP基本交互*************************** HTTP请求格式:HTTP 请求由三部分组成:请求行.请求头和请求正文请求行: 请求方 ...
- 吐血分享:QQ群霸屏技术教程2017(活跃篇)
热门词的群排名,在前期优化准备充分的情况下,活跃度不失为必杀技. 在<吐血分享:QQ群霸屏技术(初级篇)>中,我们提及到热门词的群排名,有了前面的基础,我们就可以进入深度优化,实现绝对的霸 ...
- C语言实例解析精粹学习笔记——35(报数游戏)
实例35: 设由n个人站成一圈,分别被编号1,2,3,4,……,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...
- 毕业2年 Summary
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/135 看了下去年写毕业一周年总结的时间:2017-6-16,今天 ...
- SIMD数据并行(二)——多媒体SIMD扩展指令集
在计算机体系中,数据并行有两种实现路径:MIMD(Multiple Instruction Multiple Data,多指令流多数据流)和SIMD(Single Instruction Multip ...
- Spring 的好处?
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监 ...