Assets, Resources and AssetBundles(4)翻译
4.AssetBundle fundamentals
This chapter discusses AssetBundles. It introduces the fundamental systems upon which AssetBundles are built, as well as the core APIs used to interact with AssetBundles. In particular, it discusses both the loading and unloading of AssetBundles themselves, as well as the loading and unloading of specific Asset and Objects from AssetBundles.
本章讨论AssetBundles。它介绍了构建AssetBundles所基于的基本系统,以及用于与AssetBundles交互的核心APIs。特别地,它讨论了AssetBundles本身的加载和卸载,以及从AssetBundle中加载和卸载特定资产和对象。
For more patterns and best practices on the uses of AssetBundles, see the next chapter in this series.
有关AssetBundles使用的更多模式和最佳实践,请参阅本系列的下一章。
4.1. Overview
The AssetBundle system provides a method for storing one or more files in an archival format that Unity can index and serialize. AssetBundles are Unity's primary tool for the delivery and updating of non-code content after installation. This permits developers to submit a smaller app package, minimize runtime memory pressure, and selectively load content optimized for the end-user's device.
AssetBundle 系统提供了一种方法,以档案格式(archival format)存储一个或多个文件,以便Unity可以索引和序列化。AssetBundles是Unity在安装后交付和更新非代码内容的主要工具。这允许开发人员提交更小的应用程序包,最小化运行时内存压力,并有选择地加载针对终端用户设备优化的内容。
Understanding the way AssetBundles work is essential to building a successful Unity project for mobile devices. For an overall description of AssetBundle contents, review the AssetBundle documentation.
理解AssetBundles的工作方式对于构建一个成功的移动设备Unity项目至关重要。对于AssetBundle内容的总体描述,请查看AssetBundle文档。
4.2. AssetBundle layout
To summarize, an AssetBundle consists of two parts: a header and data segment.
总的来说,一个AssetBundle 由两个部分组成:头和数据段。
The header contains information about the AssetBundle, such as its identifier, compression type, and a manifest. The manifest is a lookup table keyed by an Object's name. Each entry provides a byte index that indicates where a given Object can be found within the AssetBundle's data segment. On most platforms, this lookup table is implemented as a balanced search tree. Specifically, Windows and OSX-derived platforms (including iOS) employ a red-black tree. Therefore, the time needed to construct the manifest will increase more than linearly as the number of Assets within an AssetBundle grows.
头包含有关AssetBundle的信息,例如它的标识符(identifier)、压缩类型(compression type)和清单(manifest)。清单是一个以对象名称为键的查找表。每个条目提供一个字节索引,指示在AssetBundle的数据段中可以找到给定对象的位置。在大多数平台上,这个查询表被实现为一个平衡搜索树。具体来说,Windows和osx派生平台(包括iOS)使用了一个红黑树。因此,构造清单(manifest)所需的时间将随着AssetBundle中的资产数量超过线性时间增加。【注:即构建红黑树的时间复杂度为O(NlogN)】
The data segment contains the raw data generated by serializing the Assets in the AssetBundle. If LZMA is specified as the compression scheme, the complete byte array for all serialized assets is compressed. If LZ4 is instead specified, bytes for separate Assets are individually compressed. If no compression is used, the data segment will remain as raw byte streams.
数据段包含通过序列化AssetBundle中的Assets而生成的原始数据(raw data)。如果将LZMA指定为压缩方案,则将压缩所有序列化资产的完整字节数组。如果指定了LZ4(压缩方案),不同Assets的字节将单独压缩。如果没有使用压缩,数据段将保持为原始字节流(raw byte streams)。
Prior to Unity 5.3, Objects could not be compressed individually inside an AssetBundle. As a consequence, if a version of Unity before 5.3 is instructed to read one or more Objects from a compressed AssetBundle, Unity had to decompress the entire AssetBundle. Generally, Unity cached a decompressed copy of the AssetBundle to improve loading performance for subsequent loading requests on the same AssetBundle.
在Unity 5.3之前,对象不能被单独压缩在一个AssetBundle中。因此,如果Unity在5.3之前的版本被要求从压缩的AssetBundle中读取一个或多个对象,那么Unity就必须对整个AssetBundle进行解压缩。通常,Unity会缓存一个AssetBundle的解压缩副本,以提高后续在同一AssetBundle上的加载请求的加载性能。
4.3. Loading AssetBundles
AssetBundles can be loaded via four distinct APIs. The behavior of these four APIs is different depending on two criteria:
AssetBundle 可以通过四个不同的APIs加载。这四个APIs的行为是不同的,取决于两个标准:
-
Whether the AssetBundle is LZMA compressed, LZ4 compressed or uncompressed
-
The platform on which the AssetBundle is being loaded
- AssetBundle 是否LZMA压缩,LZ4压缩或未压缩
- 加载AssetBundle 的平台
These APIs are:
-
AssetBundle.LoadFromMemory(Async optional)
-
AssetBundle.LoadFromFile(Async optional)
-
UnityWebRequest's DownloadHandlerAssetBundle
-
WWW.LoadFromCacheOrDownload (on Unity 5.6 or older)
4.3.1 AssetBundle.LoadFromMemory(Async)
Unity's recommendation is not to use this API.
Unity的建议是不使用这个API。
AssetBundle.LoadFromMemoryAsync loads an AssetBundle from a managed-code byte array (byte[] in C#). It will always copy the source data from the managed-code byte array into a newly-allocated, contiguous block of native memory. If the AssetBundle is LZMA compressed, it will decompress the AssetBundle while copying. Uncompressed and LZ4-compressed AssetBundles will be copied verbatim.
AssetBundle.LoadFromMemoryAsync从托管代码字节数组(C#中的byte[])加载一个AssetBundle 。它总是将源数据从托管代码字节数组复制到新分配的本机连续内存块中。如果AssetBundle是LZMA压缩的,它将在复制时解压AssetBundle 。未压缩和lz4压缩的AssetBundle 将被逐字(verbatim)复制。
The peak amount of memory consumed by this API will be at least twice the size of the AssetBundle: one copy in native memory created by the API, and one copy in the managed byte array passed to the API. Assets loaded from an AssetBundle created via this API will therefore be duplicated three times in memory: once in the managed-code byte array, once in the native-memory copy of the AssetBundle and a third time in GPU or system memory for the asset itself.
这个API消耗的内存峰值将至少是AssetBundle 大小的两倍:一个在本机内存中由API创建的副本,一个从托管字节数组中传递给API的副本。因此,通过这个API创建的AssetBundle 加载的资产将在内存中复制三次:一次在托管代码字节数组中,一次在AssetBundle 的本地内存副本中,第三次在GPU或系统内存中为复制资产本身。
Prior to Unity 5.3.3, this API was known as **AssetBundle.CreateFromMemory**. Its functionality has not changed.
在Unity 5.3.3之前,这个API被称为**AssetBundle.CreateFromMemory**。它的功能没有改变。
4.3.2. AssetBundle.LoadFromFile(Async)
AssetBundle.LoadFromFile is a highly-efficient API intended for loading uncompressed or LZ4-compressed AssetBundle from local storage, such as a hard disk or an SD card.
AssetBundle.LoadFromFile是一个高效的API,用于从本地存储(如硬盘或SD卡)加载未压缩或LZ4压缩的AssetBundle 。
On desktop standalone, console, and mobile platforms, the API will only load the AssetBundle's header, and will leave the remaining data on disk. The AssetBundle's Objects will be loaded on-demand as loading methods (e.g. AssetBundle.Load) are called or as their InstanceIDs are dereferenced. No excess memory will be consumed in this scenario. In the Unity Editor, the API will load the entire AssetBundle into memory, as if the bytes were read off disk and AssetBundle.LoadFromMemoryAsync was used. This API can cause memory spikes to appear during AssetBundle loading if the project is profiled in the Unity Editor. This should not affect performance on-device and these spikes should be re-tested on-device before taking remedial action.
在独立桌面、控制台和移动平台上,API将只加载AssetBundle的头文件,并将剩余的数据留在磁盘上。当加载方法(例如AssetBundle. Load)被调用或者当它们(指AssetBundle中的对象)的Instance ID被解引用时【注:解引用:获取引用所指向的对象】,AssetBundle的对象将按需加载。这种情况中不会消耗多余的内存。在Unity编辑器中,API将加载整个AssetBundle到内存中,就像使用AssetBundle.LoadFromMemoryAsync从磁盘中读取(read off:从...读取)字节一样。如果在Unity使用Prifiler对项目进行分析,这个API会导致在AssetBundle加载期间出现内存峰值
Note: On Android devices with Unity 5.3 or older, this API will fail when trying to load AssetBundles from the Streaming Assets path. This issue has been resolved in Unity 5.4. For more details, see the section Distribution - shipped with project section of the AssetBundle usage patterns step.
注意:在Unity 5.3或更老版本的Android设备上,当试图从Streaming Assets路径加载AssetBundle时,这个API将会失败。这个问题已经在Unity 5.4中解决了。有关更多细节,请参阅Distribution - shipped with project section of the AssetBundle usage patterns step.
Prior to Unity 5.3, this API was known as **AssetBundle.CreateFromFile**. Its functionality has not been changed.
在Unity 5.3之前,这个API被称为** AssetBundle.CreateFromFile**。它的功能没有改变。
4.3.3. AssetBundleDownloadHandler
The UnityWebRequest API allows developers to specify exactly how Unity should handle downloaded data and allows developers to eliminate unnecessary memory usage. The simplest way to download an AssetBundle using UnityWebRequest is to call UnityWebRequest.GetAssetBundle.
UnityWebRequest API允许开发者精确地指定Unity应该如何处理下载数据,并允许开发者消除不必要的内存使用。使用UnityWebRequest下载一个AssetBundle 最简单的方法是调用UnityWebRequest.GetAssetBundle。
For the purposes of this guide, the class of interest is DownloadHandlerAssetBundle. Using a worker thread, it streams downloaded data into a fixed-size buffer and then spools the buffered data to either temporary storage or the AssetBundle cache, depending on how the Download Handler has been configured. All of these operations occur in native code, eliminating the risk of expanding the managed heap. Additionally, this Download Handler does not keep a native-code copy of all downloaded bytes, further reducing the memory overhead of downloading an AssetBundle.
出于本指南的目的,我们感兴趣的类是DownloadHandlerAssetBundle。它使用一个工作线程,将下载的数据流到一个固定大小的缓冲区,然后将缓冲的数据发送到临时存储或AssetBundle缓存,这取决于下载处理程序(Download Handler)的配置方式。所有这些操作都在本机代码中进行,从而消除了托管堆扩大的风险。此外,这个下载处理程序不保留所有下载字节的原生代码副本,进一步减少了下载一个AssetBundle的内存开销。
LZMA-compressed AssetBundles will be decompressed during download and cached using LZ4 compression. This behavior may be changed by setting Caching.CompressionEnabled.
When the download is complete, the assetBundle property of the Download Handler provides access to the downloaded AssetBundle, as if AssetBundle.LoadFromFile had been called on the downloaded AssetBundle.
下载完成后,下载处理程序的assetBundle属性提供对下载的AssetBundle的访问,就像对AssetBundle.LoadFromFile已在下载的AssetBundle上被调用过一样。
If caching information is provided to a UnityWebRequest object, and the requested AssetBundle already exists in Unity's cache, then the AssetBundle will become available immediately and this API will operate identically to AssetBundle.LoadFromFile.
如果缓存信息被提供给一个UnityWebRequest对象,并且被请求的AssetBundle 已经存在于Unity的缓存中,那么这个AssetBundle将立即可用,并且这个API将与AssetBundle.LoadFromFile操作相同。
Prior to Unity 5.6, the UnityWebRequest system used a fixed pool of worker threads and an internal job system to safeguard against excessive, concurrent downloads. The size of the thread pool was not configurable. In Unity 5.6, these safeguards have been removed to accommodate more modern hardware, and allow for faster access to HTTP response codes and headers.
在Unity 5.6之前,UnityWebRequest系统使用一个固定的工作线程池和一个内部的作业系统来防止过多的并发下载。线程池的大小不可配置。在Unity 5.6中,这些安全措施已经被移除,以适应更现代化的硬件,并允许更快地访问HTTP响应代码和头信息。
4.3.4. WWW.LoadFromCacheOrDownload
Note: Beginning in Unity 2017.1, WWW.LoadFromCacheOrDownload simply wraps around UnityWebRequest. Accordingly, developers using Unity 2017.1 or higher should migrate to UnityWebRequest. WWW.LoadFromCacheOrDownload will be deprecated in a future release.
注意:从Unity 2017.1开始,WWW.LoadFromCacheOrDownload只是简单地封装了UnityWebRequest。因此,使用Unity 2017.1或更高版本的开发者应该迁移到UnityWebRequest。WWW.LoadFromCacheOrDownload将在未来的版本中被弃用。
The following information is applicable to Unity 5.6 or older.
以下信息适用于Unity 5.6或更早版本。
WWW.LoadFromCacheOrDownload is an API that allows loading of Objects from both remote servers and local storage. Files can be loaded from local storage via a file:// URL. If the AssetBundle is present in the Unity cache, this API will behave exactly like AssetBundle.LoadFromFile.
WWW.LoadFromCacheOrDownload是一个API,它允许从远程服务器和本地存储加载对象。文件可以通过file:// URL从本地存储中加载。如果AssetBundle存在于Unity缓存中,这个API将会像AssetBundle.Loadfromfile一样运行。
If an AssetBundle has not yet been cached, then WWW.LoadFromCacheOrDownload will read the AssetBundle from its source. If the AssetBundle is compressed, it will be decompressed using a worker thread and written into the cache. Otherwise, it will be written directly into the cache via the worker thread. Once the AssetBundle is cached, WWW.LoadFromCacheOrDownload will load header information from the cached, decompressed AssetBundle. The API will then behave identically to an AssetBundle loaded with AssetBundle.LoadFromFile. This cache is shared between WWW.LoadFromCacheOrDownload and UnityWebRequest. Any AssetBundle downloaded with one API will also be available via the other API.
While the data will be decompressed and written to the cache via a fixed-size buffer, the WWW object will keep a full copy of the AssetBundle's bytes in native memory. This extra copy of the AssetBundle is kept to support the WWW.bytes property.
如果一个AssetBundle 还没有被缓存,那么WWW.LoadFromCacheOrDownload将从源文件中读取AssetBundle 。如果AssetBundle 被压缩,那么它将使用一个工作线程解压并写入缓存中。否则,它将通过工作线程直接写入缓存。一旦AssetBundle 被缓存,WWW.LoadFromCacheOrDownload将从缓存的、已解压的资源包中加载头信息。然后,API的行为将与用AssetBundle.Loadfromfile加载AssetBundle 相同。此缓存在WWW.LoadFromCacheOrDownload UnityWebRequest之间共享。通过一个API下载的任何AssetBundle 也可以通过另一个API使用。当数据将被解压并通过一个固定大小的缓冲区写入缓存时,WWW对象将在本机内存中保留一个AssetBundle字节的完整副本。这个额外的AssetBundle 副本是用来支持WWW.bytes属性。
Due to the memory overhead of caching an AssetBundle's bytes in the WWW object, AssetBundles should remain small - a few megabytes, at most. For more discussion of AssetBundle sizing, see theAsset assignment strategies section in theAssetBundle usage patterns chapter.
由于在WWW对象中缓存一个AssetBundle的字节的内存开销,AssetBundles应该保持较小——最多几兆字节。有关AssetBundle规模的更多讨论,请参阅Asset assignment strategies section in theAssetBundle usage patterns chapter.
Unlike UnityWebRequest, each call to this API will spawn a new worker thread. Accordingly, on platforms with limited memory, such as mobile devices, only a single AssetBundle at a time should be downloaded using this API, in order to avoid memory spikes. Be careful of creating an excessive number of threads when calling this API multiple times. If more than 5 AssetBundles need to be downloaded, create and manage a download queue in script code to ensure that only a few AssetBundle downloads are running simultaneously.
与UnityWebRequest不同,对这个API的每次调用都会产生一个新的工作线程。因此,在内存有限的平台上,比如移动设备,为了避免内存峰值,只能使用这个API每次只能下载一个AssetBundle 。在多次调用此API时,要小心创建过多的线程。如果需要下载超过5个AssetBundle ,在脚本代码中创建并管理一个下载队列,以确保只有少数AssetBundle 下载在同时运行。
4.3.5. Recommendations
In general, AssetBundle.LoadFromFile should be used whenever possible. This API is the most efficient in terms of speed, disk usage and runtime memory usage.
一般来说,应该尽可能使用LoadFromFile.AssetBundle。这个API在速度、磁盘使用和运行时内存使用方面是最有效的。
For projects that must download or patch AssetBundles, it is strongly recommended to useUnityWebRequest for projects using Unity 5.3 or newer, and WWW.LoadFromCacheOrDownload for projects using Unity 5.2 or older. As detailed in theDistribution section, it is possible to prime the AssetBundle Cache with Bundles included within a project's installer.
对于那些必须下载AssetBundles或使用AssetBundles打补丁的项目,在Unity 5.3或更新版本,强烈推荐使用UnityWebRequest。WWW.LoadFromCacheOrDownload用于使用Unity 5.2或更老版本的项目。正如分发部分中所详细介绍的,可以在项目安装的时候(下载器)将 AssetBundle包 解压从而事先准备好 AssetBundle缓存。
When using either UnityWebRequest or WWW.LoadFromCacheOrDownload, ensure that the downloader code properly calls Dispose after loading the AssetBundle. Alternately, C#'s using statement is the most convenient way to ensure that a WWW or UnityWebRequest is safely disposed of.
当使用UnityWebRequest或WWW.LoadFromCacheOrDownload时,确保下载器代码在加载资产包后正确调用Dispose。另外,C#的using语句是确保WWW或UnityWebRequest被安全销毁的最方便的方法。
For projects with substantial engineering teams that require unique, specific caching or downloading requirements, a custom downloader may be considered. Writing a custom downloader is a non-trivial engineering task, and any custom downloader should be made compatible with AssetBundle.LoadFromFile. See the Distribution section of the next step for more details.
对于一个有着大型开发团队的项目来说,需要独特的、特定的缓存或下载要求,可以考虑定制下载器。编写一个自定义下载程序是一项重要的工程任务,并且任何自定义下载程序都应该与AssetBundle.LoadFromFile兼容。有关更多细节,请参阅Distribution section of the next step for more details.
4.4. Loading Assets From AssetBundles
UnityEngine.Objects can be loaded from AssetBundles using three distinct APIs that are all attached to the AssetBundle object, which have both synchronous and asynchronous variants:
UnityEngine.Objects 可以使用三种不同的API从AssetBundle中加载对象,这些对象都附加在AssetBundle上,它们有同步和异步的变体:
The synchronous versions of these APIs will always be faster than their asynchronous counterpart, by at least one frame.
这些API的同步版本总是比对应的异步版本快至少一帧。
Asynchronous loads will load multiple Objects per frame, up to their time-slice limits. See theLow-level loading details section for the underlying technical reasons for this behavior.
异步加载将在每帧加载多个对象,直到达到它们的时间片限制为止。有关此行为的基本技术原因,请参阅Low-level loading details section。
LoadAllAssets should be used when loading multiple independent UnityEngine.Objects. It should only be used when the majority or all of the Objects within an AssetBundle need to be loaded. Compared to the other two APIs, LoadAllAssets is slightly faster than multiple individual calls to LoadAssets. Therefore, if the number of assets to be loaded is large, but less than 66% of the AssetBundle needs to be loaded at a single time, consider splitting the AssetBundle into multiple smaller bundles and using LoadAllAssets.
加载多个独立的UnityEngine.Objects时应该使用LoadAllAssets。只有当AssetBundle中的大多数或所有对象需要加载时,才应该使用它。与其他两个APIs相比,LoadAllAssets比多次调用LoadAssets要略微快一些。因此,如果要加载的资产数量很大,但是一次需要加载的资产包少于66%,可以考虑将资产包拆分为多个更小的包,并使用LoadAllAssets。
LoadAssetWithSubAssets should be used when loading a composite Asset which contains multiple embedded Objects, such as an FBX model with embedded animations or a sprite atlas with multiple sprites embedded inside it. If the Objects that need to be loaded all come from the same Asset, but are stored in an AssetBundle with many other unrelated Objects, then use this API.
LoadAssetWithSubAssets应该在加载包含多个嵌入对象的composite Asset时使用,例如一个带有嵌入动画的FBX模型或一个内嵌多个精灵的精灵图集。如果需要加载的对象都来自相同的Asset,但与许多其他不相关的对象存储在一个AssetBundle中,那么就使用这个API。
For any other case, use LoadAsset or LoadAssetAsync.
对于任何其他情况,使用LoadAsset或LoadAssetAsync。
4.4.1. Low-level loading details
UnityEngine.Object loading is performed off the main thread: an Object's data is read from storage on a worker thread. Anything which does not touch thread-sensitive parts of the Unity system (scripting, graphics) will be converted on the worker thread. For example, VBOs will be created from meshes, textures will be decompressed, etc.
UnityEngine.Object 加载是在主线程上执行的:对象的数据从工作线程的存储中读取。任何不触及Unity系统的线程敏感部分(脚本、图形)都将在工作线程上转换。例如,VBOs将从网格创建,纹理将被解压,等等。
From Unity 5.3 onward, Object loading has been parallelized. Multiple Objects are deserialized, processed and integrated on worker threads. When an Object finishes loading, its Awake callback will be invoked and the Object will become available to the rest of the Unity Engine during the next frame.
从Unity 5.3开始,对象加载就被并行化了。多个对象在工作线程上被反序列化、处理和集成。当一个对象完成加载时,它的Awake回调将被调用,并且在下一帧中对象将对Unity引擎的其余对象可用。
The synchronous AssetBundle.Load methods will pause the main thread until Object loading is complete. They will also time-slice Object loading so that Object integration does not occupy more than a certain number of milliseconds of frame time. The number of milliseconds is set by the property Application.backgroundLoadingPriority:
同步AssetBundle.Load方法将暂停主线程,直到对象加载完成。它们还将对对象加载进行时间切片,以便对象集成占用的帧时间不会超过一定的毫秒数。毫秒数由属性Application.backgroundLoadingPriority设置:
-
ThreadPriority.High: Maximum 50 milliseconds per frame
-
ThreadPriority.Normal: Maximum 10 milliseconds per frame
-
ThreadPriority.BelowNormal: Maximum 4 milliseconds per frame
-
ThreadPriority.Low: Maximum 2 milliseconds per frame.
From Unity 5.2 onwards, multiple Objects are loaded until the frame-time limit for Object loading is reached. Assuming all other factors are equal, the asynchronous variants of the asset loading APIs will always take longer to complete than the comparable synchronous version due to the minimum one-frame delay between issuing the asynchronous call and the object becoming available to the Engine.
从Unity 5.2开始,可以加载多个对象,直到达到对象加载的帧时间限制。假设所有其他因素都相同,asset加载APIs的异步变体总是比可比的同步版本花费更长的时间来完成,因为在发出异步调用和对引擎可用的对象之间有最小为一帧延迟。
4.4.2. AssetBundle dependencies
The dependencies among AssetBundles are automatically tracked using two different APIs, depending on the runtime environment. In the Unity Editor, AssetBundle dependencies can be queried via the AssetDatabase API. AssetBundle assignments and dependencies can be accessed and changed via the AssetImporter API. At runtime, Unity provides an optional API to load the dependency information generated during an AssetBundle build via a ScriptableObject-based AssetBundleManifest API.
根据运行时环境,使用两种不同的APIs自动跟踪资产包之间的依赖关系。在Unity编辑器中,可以通过AssetDatabase API查询资产包依赖关系。资产包分配和依赖关系可以通过AssetImporter API访问和更改。在运行时,Unity提供了一个可选的基于scriptableobject的AssetBundleManifest API来加载在构建资产包时生成的依赖信息。
An AssetBundle is dependent upon another AssetBundle when one or more of the parent AssetBundle's UnityEngine.Objects refers to one or more of the other AssetBundle's UnityEngine.Objects. For more information on inter-Object references, see theInter-Object references section of theAssets, Objects and Serialization step.
当一个或多个父资产包的UnityEngine.Object引用其他AssetBundle的一个或多个UnityEngine.Objects时,一个AssetBundle依赖于另一个AssetBundle。有关对象间引用的更多信息,请参阅Inter-Object references section of theAssets, Objects and Serialization 部分.
As described in the Serialization and instances section of that step, AssetBundles serve as sources for the source data identified by the FileGUID & LocalID of each Object contained within the AssetBundle.
如Serialization and instances部分所述,AssetBundles充当由AssetBundle中包含的每个对象的File GUID和Local ID标识的源数据的源。
Because an Object is loaded when its Instance ID is first dereferenced, and because an Object is assigned a valid Instance ID when its AssetBundle is loaded, the order in which AssetBundles are loaded is not important. Instead, it is important to load all AssetBundles that contain dependencies of an Object before loading the Object itself. Unity will not attempt to automatically load any child AssetBundles when a parent AssetBundle is loaded.
因为一个对象是在它的Instance ID第一次解引用时被加载的,并且在它的资产包被加载时被分配了一个有效的Instance ID,所以AssetBundles 被加载顺序并不重要。相反,重要的是在加载对象本身之前加载所有包含对象依赖项的AssetBundles。当父AssetBundle 被加载时,Unity不会尝试自动加载任何AssetBundles。
Example:
Assume material A refers to texture B. Material A is packaged into AssetBundle 1, and texture B is packaged into AssetBundle 2.
假设Material A引用texture B。Material A被打包到AssetBundle 1中,texture B被打包到AssetBundle 2中。
In this use case, AssetBundle 2 must be loaded prior to loading Material A out of AssetBundle 1.
在这个用例中,必须在从AssetBundle 1中加载Material A之前加载AssetBundle 2。
This does not imply that AssetBundle 2 must be loaded before AssetBundle 1, or that Texture B must be loaded explicitly from AssetBundle 2. It is sufficient to have AssetBundle 2 loaded prior to loading Material A out of AssetBundle 1.
这并不意味着AssetBundle 2必须在AssetBundle 1之前加载,或者Texture B必须从AssetBundle 2显式加载。在从AssetBundle 1中加载Material A之前加载AssetBundle 2就足够了。
However, Unity will not automatically load AssetBundle 2 when AssetBundle 1 is loaded. This must be done manually in script code.
但是,当AssetBundle 1被加载时,Unity不会自动加载AssetBundle 2。这必须在脚本代码中手动完成。
For more information on AssetBundle dependencies, refer to the manual page.
有关资产包依赖关系的更多信息,请参阅manual page。
4.4.3. AssetBundle manifests
When executing the AssetBundle build pipeline using the BuildPipeline.BuildAssetBundles API, Unity serializes an Object containing each AssetBundle's dependency information. This data is stored in a separate AssetBundle, which contains a single Object of the AssetBundleManifest type.
当使用BuildPipeline.BuildAssetBundles API执行AssetBundle构建管线时。Unity序列化一个对象,包含每个AssetBundle的依赖信息。该数据存储在一个单独的AssetBundle中,其中包含一个AssetBundleManifest类型的对象。
This Asset will be stored in an AssetBundle with the same name as the parent directory where the AssetBundles are being built. If a project builds its AssetBundles to a folder at (projectroot)/build/Client/, then the AssetBundle containing the manifest will be saved as (projectroot)/build/Client/Client.manifest.
该Asset 将存储在与构建AssetBundles的父目录同名的AssetBundle中。如果一个项目将其AssetBundles构建到(projectroot)/build/Client/处的文件夹中,那么包含清单的AssetBundle 将保存为(projectroot)/build/Client/Client.manifest。
The AssetBundle containing the manifest can be loaded, cached and unloaded just like any other AssetBundle.
包含清单的AssetBundle 可以像其他AssetBundle一样被加载、缓存和卸载。
The AssetBundleManifest Object itself provides the GetAllAssetBundles API to list all AssetBundles built concurrently with the manifest and two methods to query the dependencies of a specific AssetBundle:
AssetBundleManifest对象本身提供了GetAllAssetBundles API来列出所有与manifest并发构建的AssetBundles,还有两种方法来查询特定资产包的依赖关系:
-
AssetBundleManifest.GetAllDependencies returns all of an AssetBundle's hierarchical dependencies, which includes the dependencies of the AssetBundle's direct children, its children's children, etc.
- AssetBundleManifest.GetAllDependencies返回一个AssetBundle的所有层次依赖关系,其中包括AssetBundle的直接子组件、其子组件的子组件等等的依赖关系。
-
AssetBundleManifest.GetDirectDependencies returns only an AssetBundle's direct children
- AssetBundleManifest.GetDirectDependencies只返回一个AssetBundle的直接子组件
Note that both of these APIs allocate string arrays. Accordingly, they should only be used sparingly, and not during performance-sensitive portions of an application's lifetime.
注意,这两个APIs都分配字符串数组。因此,它们应该只被有节制地使用,而不是在应用程序生命周期中对性能敏感的部分使用。
4.4.4. Recommendations
In many cases, it is preferable to load as many needed Objects as possible before players enter performance-critical areas of an application, such as the main game level or world. This is particularly critical on mobile platforms, where access to local storage is slow and the memory churn of loading and unloading Objects at play-time can trigger the garbage collector.
在许多情况下,最好在玩家进入应用程序的性能关键区域(performance-critical areas of an application)(如主要游戏关卡或世界)之前加载尽可能多的所需对象。这在移动平台上尤为重要,在移动平台上,对本地存储的访问非常缓慢,并且在运行时加载和卸载对象的内存搅动可能会触发垃圾收集器。
For projects that must load and unload Objects while the application is interactive, see theManaging loaded assets section of the AssetBundle usage patterns step for more information on unloading Objects and AssetBundles.
对于必须在应用程序交互时加载和卸载对象的项目,请参阅Managing loaded assets section of the AssetBundle usage patterns,以获得更多关于卸载对象和AssetBundles的信息。