zoukankan      html  css  js  c++  java
  • AssetBundles

    AssetBundles针对特定平台的可以在运行时加载的资源包
    有相互依赖关系
    两部分构成:archive(文档,包含serialized file 和 resource files);AssetBundle object(包含一个path到assets的map)
    文件只能放.txt后缀的文件,.lua的要在打包前加上.txt后缀 - -

    可以在Inspector的下方选择资源所在的Bundle,然后用代码打包
    public class CreateAssetBundles
    {
        [MenuItem("Assets/Build AssetBundles")]
        static void BuildAllAssetBundles()
        {
            string assetBundleDirectory = "Assets/AssetBundles";
            if(!Directory.Exists(assetBundleDirectory)
            {
                Directory.CreateDirectory(assetBundleDirectory);
            }
            BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.Standalone);
        }
    }
    加载代码如下
    public class LoadFromFileExample extends MonoBehaviour {
        function Start() {
            var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
            if (myLoadedAssetBundle == null) {
                Debug.Log("Failed to load AssetBundle!");
                return;
            }
            var prefab = myLoadedAssetBundle.LoadAsset.<GameObject>("MyObject");
            Instantiate(prefab);
        }
    }
    从服务器下载
        IEnumerator InstantiateObject()
        {
            string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;        
            UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
            yield return request.Send();
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
            GameObject cube = bundle.LoadAsset<GameObject>("Cube");
            GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
            Instantiate(cube);
            Instantiate(sprite);
        }

    分组策略
        Logical Entity Grouping,Type Grouping(平台差异化好弄),Concurrent Content Grouping(同时会用到的打成一组,最常见的是基于scenes)

    Building AssetBundles
        BuildAssetBundleOptions,三种压缩方式
            None:使用LZMA压缩.使用前要解压整个包.解压一次后用LZ4重新压缩,不再需要解压全部包
            UncompressedAssetBundle:
            ChunkBasedCompression:LZ4压缩,比LZMA大
        其他参数 https://docs.unity3d.com/ScriptReference/BuildAssetBundleOptions.html

        BuildTarget:选择平台, EditorUserBuildSettings.activeBuildTarget 当前平台

    产生文件
        会生成 2*(n+1)个文件
        .u                             二进制文件
        .manifest                 文本文件,包的关联和依赖关系
        Bundles                   
        Bundles.manifest    
        
    AssetBundle Dependencies
        一个包引用另一个包的资源会产生依赖,Unity不会自动加载依赖包

    Using AssetBundles Natively
        4个API接口
        AssetBundle.LoadFromMemoryAsync
        AssetBundle.LoadFromFile  (load未解压的包,最高效)
        WWW.LoadfromCacheOrDownload(UnityWebRequest 的过时版本)
        UnityWebRequest’s DownloadHandlerAssetBundle (Unity 5.3 or newer, 更优的方案是使用 UnityEngine.WWW 类)
        
    Load Assets
        同步 T objectFromBundle = bundleObject.LoadAsset<T>(assetName);
        异步 
    AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);
    yield return request;
    var loadedAsset = request.asset;

    Loading AssetBundle Manifests    
    用以处理包的依赖关系
    AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
    AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    string[] dependencies = manifest.GetAllDependencies("assetBundle"); //Pass the name of the bundle you want the dependencies for.
    foreach(string dependency in dependencies)
    {
        AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
    }

    Managing Loaded AssetBundles
    需要手动管理bundle的加载和卸载
    AssetBundle.Unload(bool unloadAllLoadedObjects); 
        卸载该bundle全部资源
      unloadAllLoadedObjects 
            false已经加载的保持(但是连接关系会被破坏,造成未预想情况,必须在消除所有引用后调用 Resources.UnloadUnusedAssets 清除)
            true已经加载的会卸载和销毁,建议使用

    建议: 1 明确的bundle卸载点,比如切换场景(切场景会自动调用Resources.UnloadUnusedAssets)
               2 维持资源引用计数

    Patching with AssetBundles
        下载新的替换老的就行了

    Asset Duplication 问题
    某个资源自身没有指明bundle包,但别的bundle包引用了它时,有可能产生重复资源
        1 确保对象建立不同的资源不共享的依赖关系。
        2 确保所有依赖资产纳入自己的资源包
    UnityEditor.AssetDatabase 可以检查资源依赖项
    AssetImporter 接口可以查询资源包对象

    AssetBundles-Browser工具,可以查看包内容依赖
    https://github.com/Unity-Technologies/AssetBundles-Browser

    Streaming Assets
        把打包好的Bundle放在StreamingAssets文件夹下,打包时会打到包里,安装时会放在对应的目录中,
        用Application.streamingAssetsPath接口获取对应路径
        On a desktop computer (Mac OS or Windows) the location of the files can be obtained with the following code:
            path = Application.dataPath + "/StreamingAssets";
        On iOS, use:
            path = Application.dataPath + "/Raw";
        On Android, use:
            path = "jar:file://" + Application.dataPath + "!/assets/";



    使用笔记

    三个关键库:
        AssetDatabase 
            提供了查找资源、加载资源、创建资源,删除资源和修改资源的方法。Unity编辑器内部使用AssetDatabase保持跟踪资源文件和保持资源与引用它们的对象之间的关联。由于Unity需要保持跟踪项目文件夹中的所有更改,如果你想访问或修改的资源数据,你应该始终使用AssetDatabase API,而不是文件系统。
        AssetImporter 
            资源设置,一般用来带资源所在包,可以对文件夹设置,其下的全部自动加入
                AssetImporter import = AssetImporter.GetAtPath(path);
                import.assetBundleName = name + ".u";
        BuildPipeline 
            打包管线

    实际上使用 U3D推荐的Unity Asset Bundle Browser tool就可以了,稍微扩展一下就好

    一些可能的处理函数
    	//清空bunle配置
    	void Clean()
    	{
    		string[] names = AssetDatabase.GetAllAssetBundleNames();
    		foreach (var name in names)
    		{
    			AssetDatabase.RemoveAssetBundleName(name, true);
    		}
    		AssetDatabase.RemoveUnusedAssetBundleNames();
    
    		AssetDatabase.Refresh();
    		AssetDatabase.SaveAssets();
    	}
    
    	//复制Lua加上txt并转存到另一个文件夹
    	void CopyLuaTxtFile()
    	{
    		if (Directory.Exists(Paths.luaTxt))
    		{
    			Directory.Delete(Paths.luaTxt, true);
    		}
    
    		Directory.CreateDirectory(Paths.luaTxt);
    
    		List<string> luas = GetFiles(new DirectoryInfo(Paths.lua));
    		float step = luas.Count > 0 ? (1.0f / luas.Count) : 1.0f;
    		float prog = 0.0f;
    
    		foreach (string lua in luas)
    		{
    			prog += step;
    			EditorUtility.DisplayProgressBar("Copy LUA", lua, prog);
    
    			string gen = lua.Replace(Paths.lua, Paths.luaTxt) + ".txt";
    			string path = Path.GetDirectoryName(gen);
    			if (!Directory.Exists(path)) Directory.CreateDirectory(path);
    			File.Copy(lua, gen, true);
    		}
    	}
    
    	//改变一个资源(可以是文件夹)的bundle属性
    	void GenerateBundleInfo(string path, string bundleName)
    	{
    		AssetImporter import = AssetImporter.GetAtPath(path);
    		import.assetBundleName = bundleName;
    
    		AssetDatabase.Refresh();
    		AssetDatabase.SaveAssets();
    	}
    
        //一个目录下所有文件
    	static List<string> GetFiles(DirectoryInfo dir)
    	{
    		List<string> ret = new List<string>();
    		DirectoryInfo[] subs = dir.GetDirectories();
    		FileInfo[] files = dir.GetFiles();
    
    		foreach (FileInfo file in files)
    		{
    			if (file.Extension.EndsWith("meta"))
    				continue;
    
    			ret.Add(file.FullName.Replace("\", "/"));
    		}
    
    		foreach (DirectoryInfo sub in subs)
    		{
    			ret.AddRange(GetFiles(sub));
    		}
    
    		return ret;
    	}





  • 相关阅读:
    easyui tree 搜索
    easyui combotree不让父级选中
    jquery设置按钮disabled
    JavaScript中清空数组的三种方式
    JavaScript 与 PHP 的语法区别
    URL参数转换对象
    easyui form validate总是返回false原因
    jquery文字填写自动高度
    SQL Server 附加数据库提示5120错误
    jQuery – 鼠标经过(hover)事件的延时处理
  • 原文地址:https://www.cnblogs.com/Hichy/p/7743116.html
Copyright © 2011-2022 走看看