本部分将介绍使用 AssetBundle 的项目中常见的几个问题。
Unity’s AssetBundle system will discover all dependencies of an Object when the Object is built into an AssetBundle. This is done using the Asset Database. This dependency information is used to determine the set of Objects that will be included in an AssetBundle.
Assignment to AssetBundles happens at the Asset level. The Objects inside an Asset that is explicitly assigned to an AssetBundle will only be built into that single AssetBundle. Depending which signature of BuildPipeline.BuildAssetBundles is called, an Asset is “explicitly assigned” either by setting the Asset’s AssetImporter.assetBundleName property to a non-empty string, or by listing it in AssetBundleBuild.assetNames.
Any Object that is part of an Asset that is not explicitly assigned in an AssetBundle will be included in each AssetBundle that contains any Objects that reference it.
In other words, 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.
有几种方法可以解决这个问题:
确保构建到不同 AssetBundle 中的对象不共享依赖项。任何共享依赖项的对象都可以放在同一个 AssetBundle 中,而不会复制它们的依赖项。
对 AssetBundle 进行分段,确保不会同时加载两个共享依赖项的 AssetBundle。
确保所有依赖项资源都构建到自己的 AssetBundle 中。这样可以完全消除重复资源的风险,但也带来了复杂性。应用程序必须跟踪 AssetBundle 之间的依赖关系,并确保在调用任何 AssetBundle.LoadAsset API 之前加载了正确的 AssetBundle。
Object dependencies are tracked via the AssetDatabase API, located in the UnityEditor namespace. As the namespace implies, this API is only available in the Unity Editor and not at runtime. AssetDatabase.GetDependencies can be used to locate all of the immediate dependencies of a specific Object or Asset. Note that these dependencies may have their own dependencies so this can be a recursive calculation. The assignment of Assets to AssetBundles will either be defined explicitly by passing arrays of AssetBundleBuild structures when calling BuildPipeline.BuildAssetBundles, or can be queried using the AssetImporter API. It is possible to write an Editor script that ensures that all of an AssetBundle’s direct or indirect dependencies are assigned to AssetBundles, or that no two AssetBundles share dependencies that have not been assigned to an AssetBundle.
Note: When building AssetBundles with the Addressables package, the Addressables Analyze
window can be used to discover duplicated assets.
The following sections describe a quirk of asset dependency calculation code when used in conjunction with automatically-generated sprite atlases.
任何自动生成的精灵图集都将与生成精灵图集的精灵对象一起分配到同一个 AssetBundle。如果精灵对象被分配给多个 AssetBundle,则精灵图集将不会被分配给 AssetBundle 并且将被复制。如果精灵对象未分配给 AssetBundle,则精灵图集也不会分配给 AssetBundle。
为了确保精灵图集不重复,请确保标记到相同精灵图集的所有精灵都被分配到同一个 AssetBundle。
由于 Android 生态系统中存在严重的设备碎片,因此通常需要将纹理压缩为多种不同的格式。虽然所有 Android 设备都支持 ETC1,但 ETC1 不支持具有 Alpha 通道的纹理。如果应用程序不需要 OpenGL ES 2 支持,解决该问题的最简单方法是使用所有 Android OpenGL ES 3 设备都支持的 ETC2。
Most applications need to ship on older devices where ETC2 support is unavailable. One way to solve this problem is with AssetBundle Variants. (Please see Unity’s Android optimization guide for details on other options.)
要使用 AssetBundle 变体,必须将无法使用 ETC1 完全压缩的所有纹理隔离到仅包含纹理的 AssetBundle 中。接下来,使用供应商特有的纹理压缩格式(如 DXT5、PVRTC 和 ATITC),创建这些 AssetBundle 的足够多变体来支持 Android 生态系统中不支持 ETC2 的部分。对于每个 AssetBundle 变体,应将包含的纹理的 TextureImporter 设置更改为适合变体的压缩格式。
在运行时,可以使用 SystemInfo.SupportsTextureFormat API 检测对不同纹理压缩格式的支持情况。应使用此信息来选择和加载含有以受支持格式压缩的纹理的 AssetBundle 变体。
有关 Android 纹理压缩格式的更多信息,请查看此处。
When you build an AssetBundle, Unity uses information in that bundle to select which shader variants to compile. This includes information about the scenes, materials, Graphics Settings, and ShaderVariantCollections in the AssetBundle.
Separate build pipelines compile their own shaders independently of other pipelines. If both a Player build and an Addressables build reference a shader, Unity compiles two separate copies of the shader, one for each pipeline.
This process doesn’t account for any runtime information such as keywords, textures, or changes due to code execution. If you want to include specific shaders in your build, either include a ShaderVariantCollection with the desired shaders, or include the shader in your build manually by adding it to the Always Included Shaders list in your graphics settings.