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热更新的框架)打下基础 任务 ...
 
随机推荐
- js学习笔记-数字转罗马数字
			
function convert(num) { var ans = ""; var k = Math.floor(num / 1000); var h = ...
 - Android学习笔记_18_Activity生命周期 及 跳转方式
			
一.Activity有三个状态: 1.当它在屏幕前台时(位于当前任务堆栈的顶部),它是激活或运行状态.它就是响应用户操作的Activity. 2. 当它上面有另外一个Activity,使它失去了焦点但 ...
 - generative models
			
A generative model G can be seen as taking a random seed h (say, a sample from a multivariate Normal ...
 - 石头剪刀布的JAVA小程序  供初学者参考
			
package youxi; public class Player { private String name; private double score; public Player(String ...
 - CentOS 7 安装oracle 11.2.0.4 Error in invoking target 'agent nmhs' of makefile
			
%86时出现报错 Error in invoking target 'agent nmhs' of makefile 解决方案在makefile中添加链接libnnz11库的参数修改$ORACLE ...
 - Flask—06-理解掌握flask数据模型(02)
			
数据模型 模型关系 一对多(使用最多) 一:学生(Student) 需要添加反向引用 多:文章(Article) 需要添加外键关联 一对一 一:学生(Student),主表 需要添加反向引用,在一对多 ...
 - UIImagePickerController获取照片的实现,添加overlay方法 (相机取景框)
			
DEVELOPER.XIAOYAOLI 技术笔记 简单的利用UIImagePickerController调用iPhone摄像头获取照片的方法,同时介绍了怎么添加overlay,用于自定义预览界面 ...
 - ABAP术语-Authorization Object
			
Authorization Object 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/20/1006585.html Element of ...
 - spring boot 搭建基本套路《1》
			
1. Spring复习 Spring主要是创建对象和管理对象的框架. Spring通过DI实现了IoC. Spring能很大程度的实现解耦. 需要掌握SET方式注入属性的值. 需要理解自动装配. 需要 ...
 - php-5.6.26源代码 - hash存储结构 - 添加
			
添加 , (void *)module, sizeof(zend_module_entry), (void**)&module_ptr){ // zend_hash_add 定义在文件“php ...