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;
	}





原文地址:https://www.cnblogs.com/Hichy/p/7743116.html