First is the actual file on disk. This we call the AssetBundle archive, or just archive for short in this document. The archive can be thought of as a container, like a folder, that holds additional files inside of it. These additional files consist of two types; the serialized file and resource files. The serialized file contains your assets broken out into their individual objects and written out to this single file. The resource files are just chunks of binary data stored separately for certain assets (textures and audio) to allow us to load them from disk on another thread efficiently.
Second is the actual AssetBundle object you interact with via code to load assets from a specific archive. This object contains a map of all the file paths of the assets you added to this archive to the objects that belong to that asset that need to be loaded when you ask for it.
2.第二部分是脚本中使用的,例如通过unity api AssetBundle.LoadFromFile可以从指定路径加载一个AssetBundle 对象,这个要加载的对象就是上面我们说的unity里面的Asset(你可以理解成AssetBundle是一种特殊的资源,如prefabs),通过这个脚本的AssetBundle,我们可以加载出unity的AssetBundle所包含的文件
To assign a given Asset to an AssetBundle, follow these steps:
Select the asset you want to assign to a bundle from your Project View Examine the object in the inspector At the bottom of the inspector , you should see a section to assign AssetBundles and Variants: The left-hand drop down assigns the AssetBundle while the right-hand drop down assigns the variant Click the left-hand drop down where it says “None” to reveal the currently registered AssetBundle names Click “New…” to create a new AssetBundle Type in the desired AssetBundle name. Note that AssetBundle names do support a type of folder structure depending on what you type. To add sub folders, separate folder names by a “/”. For example: AssetBundle name “environment/forest” will create a bundle named forest under an environment sub folder Once you’ve selected or created an AssetBundle name, you can repeat this process for the right hand drop down to assign or create a Variant name, if you desire. Variant names are not required to build the AssetBundles
Using ChunkBasedCompression has comparable loading times to uncompressed bundles with the added benefit of reduced size on disk. 如果觉得lz4的压缩格式导致包体过大,可以将一部分ab包在压缩成lzma(将要压缩的ab包放在文件夹Temp,再将Temp压缩成LZMA格式,只在用户初次进入游戏时整个解压就好了),相当于压缩了两次
Regardless of the strategy you follow, here are some additional tips that are good to keep in mind across the board:
1.Split frequently updated objects into AssetBundles separate from objects that rarely change 2.Group objects that are likely to be loaded simultaneously. Such as a model, its textures, and its animations 3.If you notice multiple objects across multiple AssetBundles are dependant on a single asset from a completely different AssetBundle, move the dependency to a separate AssetBundle. If several AssetBundles are referencing the same group of assets in other AssetBundles, it may be worth pulling those dependencies into a shared AssetBundle to reduce duplication. 4.If two sets of objects are unlikely to ever be loaded at the same time, such as Standard and High Definition assets, be sure they are in their own AssetBundles. 6.Consider splitting apart an AssetBundle if less that 50% of that bundle is ever frequently loaded at the same time 7.Consider combining AssetBundles that are small (less that 5 to 10 assets) but whose content is frequently loaded simultaneously 8.If a group of objects are simply different versions of the same object, consider AssetBundle Variants
AssetBundles can become dependent on other AssetBundles if one or more of the UnityEngine.Objects contains a reference to a UnityEngine.Object located in another bundle. A dependency does not occur if the UnityEngine.Object contains a reference to a UnityEngine.Object that is not contained in any AssetBundle. In this case, a copy of the object that the bundle would be dependent on is copied into the bundle when you build the AssetBundles. If multiple objects in multiple bundles contain a reference to the same object that isn’t assigned to a bundle, every bundle that would have a dependency on that object will make its own copy of the object and package it into the built AssetBundle.
Should an AssetBundle contain a dependency, it is important that the bundles that contain those dependencies are loaded before the object you’re attempting to instantiate is loaded. Unity will not attempt to automatically load dependencies.
Consider the following example, a Material in Bundle 1 references a Texture in Bundle 2:
In this example, before loading the Material from Bundle 1, you would need to load Bundle 2 into memory. It does not matter which order you load Bundle 1 and Bundle 2, the important takeaway is that Bundle 2 is loaded before loading the Material from Bundle 1. In the next section, we’ll discuss how you can use the AssetBundleManifest objects we touched on in the previous section to determine, and load, dependencies at runtime.
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)); }
// 获取ABCache 不增加引用 public AssetBundleCache GetABCacheByName(string abName) { AssetBundleCache cache = null; m_AssetBundleCaches.TryGetValue (abName, out cache); return cache; }
public AssetBundleCache AddCache(string abName, AssetBundle bundle, int refCount) { if(m_AssetBundleCaches.ContainsKey (abName)) { Debugger.LogWarning ("AssetBundleCache already contains key:{0}, it will be cover by new value.", abName); }
/// <summary> /// 常驻ab包设置 /// </summary> /// <param name="arrAB"></param> public void SetPersistentABs(string[] arrAB) { m_persistentABs.Clear(); for (int i = 0; i < arrAB.Length; i++) { string strAB = FileHelper.GenBundlePath (arrAB[i]); m_persistentABs.Add(strAB);
AssetBundleCache abCache; m_AssetBundleCaches.TryGetValue(strAB, out abCache); if (abCache!=null) { abCache.Persistent = true; } } } }
八、如何卸载AssetBundle?
1 2 3 4 5 6 7 8 9 10 11
Most projects should use AssetBundle.Unload(true) and adopt a method to ensure that Objects are not duplicated. Two common methods are:
Having well-defined points during the application’s lifetime at which transient AssetBundles are unloaded, such as between levels or during a loading screen.
Maintaining reference-counts for individual Objects and unload AssetBundles only when all of their constituent Objects are unused. This permits an application to unload & reload individual Objects without duplicating memory.
If an application must use AssetBundle.Unload(false), then individual Objects can only be unloaded in two ways:
Eliminate all references to an unwanted Object, both in the scene and in code. After this is done, call Resources.UnloadUnusedAssets.
Load a scene non-additively. This will destroy all Objects in the current scene and invoke Resources.UnloadUnusedAssets automatically.
Most projects should use AssetBundle.Unload(true) and adopt a method to ensure that Objects are not duplicated. Two common methods are:
Having well-defined points during the application’s lifetime at which transient AssetBundles are unloaded, such as between levels or during a loading screen.
Maintaining reference-counts for individual Objects and unload AssetBundles only when all of their constituent Objects are unused. This permits an application to unload & reload individual Objects without duplicating memory.
If an application must use AssetBundle.Unload(false), then individual Objects can only be unloaded in two ways:
Eliminate all references to an unwanted Object, both in the scene and in code. After this is done, call Resources.UnloadUnusedAssets.
Load a scene non-additively. This will destroy all Objects in the current scene and invoke Resources.UnloadUnusedAssets automatically.
Any Object that is not explicitly assigned in an AssetBundle will be included in all AssetBundles that contain 1 or more Objects that reference the untagged Object.
If two different Objects are assigned to two different AssetBundles, but both have references to a common dependency Object, then that dependency Object will be copied into both AssetBundles. The duplicated dependency will also be instanced, meaning that the two copies of the dependency Object will be considered different Objects with a different identifiers. This will increase the total size of the application’s AssetBundles. This will also cause two different copies of the Object to be loaded into memory if the application loads both of its parents.