天天看點

Unity6.Assets, Resources and AssetBundlesA guide to AssetBundles and Resources1.Assets, Objects and serialization2.The Resources folder3.AssetBundle fundamentals4.AssetBundle usage patterns

目錄

A guide to AssetBundles and Resources

1.Assets, Objects and serialization

1.1. Inside Assets and Objects

1.2. Inter-Object references

1.6. MonoScripts

2.The Resources folder

2.1. Best Practices for the Resources System

2.2. Proper uses of the Resources system

2.3. Serialization of Resources

3.AssetBundle fundamentals

3.1. Overview

3.2. AssetBundle layout

3.3. Loading AssetBundles

3.3.1 AssetBundle.LoadFromMemory(Async)

3.3.2.AssetBundle.LoadFromFile(異步)

3.3.3. AssetBundleDownloadHandler

3.3.4. WWW.LoadFromCacheOrDownload

3.3.5. Recommendations

3.4. Loading Assets From AssetBundles

3.4.1. Low-level loading details

3.4.2. AssetBundle dependencies

3.4.3. AssetBundle manifests

3.4.4. Recommendations

4.AssetBundle usage patterns

4.1Managing loaded Assets

參考官網教程:

https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources?playlist=30089

A guide to AssetBundles and Resources

This is a series of articles that provides an in-depth discussion of Assets and resource management in the Unity engine. It seeks to provide expert developers with deep, source-level knowledge of Unity's Asset and serialization systems. It examines both the technical underpinnings of Unity's AssetBundle system and the current best practices for employing them. 提供Unity資産和序列化系統的深入源級知識。它研究了Unity的AssetBundle系統的技術基礎和目前使用它們的最佳實踐。

The guide is broken down into four chapters:

1.Assets, Objects and serialization discusses the low-level details of how Unity serializes Assets and handles references between Assets. It is strongly recommended that readers begin with this chapter as it defines terminology used throughout the guide.

2.The Resources folder discusses the built-in Resources API.

3.AssetBundle fundamentals builds on the information in chapter 1 to describe how AssetBundles operate, and discusses both the loading of AssetBundles and the loading of Assets from AssetBundles.

4.AssetBundle usage patterns is a long article discussing many of the topics surrounding the practical uses of AssetBundles. It includes sections on assigning Assets to AssetBundles and on managing loaded Assets, and describes many common pitfalls encountered by developers using AssetBundles.

1.資産,對象和序列化讨論了Unity如何序列化資産和處理資産之間引用的低級細節。強烈建議讀者從本章開始,因為它定義了整個指南中使用的術語。

2.Resources檔案夾讨論了内置的Resources API。

3.AssetBundle基礎知識建立在第1章的資訊基礎上,用于描述AssetBundles的運作方式,并讨論AssetBundles的加載和AssetBundles的資産加載。

4.AssetBundle使用模式是一篇長篇文章,讨論圍繞AssetBundles實際使用的許多主題。它包括有關将資産配置設定給AssetBundles和管理已加載資産的部分,并描述了使用AssetBundles的開發人員遇到的許多常見陷阱。

Note: This guide's terms for Objects and Assets differ from Unity's public API naming conventions. 注意:本指南的對象和資産術語與Unity的公共API命名約定不同。

The data this guide calls Objects are called Assets in many public Unity APIs, such as AssetBundle.LoadAssetand Resources.UnloadUnusedAssets. The files this guide calls Assets are rarely exposed to any public APIs. When they are exposed, it is generally only in build-related code, such as AssetDatabase and BuildPipeline. In these cases, they are called files in public APIs. 本指南稱為Objects的資料在許多公共Unity API 中稱為Assets,例如AssetBundle.LoadAsset和Resources.UnloadUnusedAssets。本指南稱之為Assets的檔案很少暴露給任何公共API。當它們被公開時,通常隻在與建構相關的代碼中,例如AssetDatabase和BuildPipeline。在這些情況下,它們在公共API 中稱為files。

1.Assets, Objects and serialization

This chapter covers the deep internals of Unity's serialization system and how Unity maintains robust references between different Objects, both in the Unity Editor and at runtime. It also discusses the technical distinctions between Objects and Assets. The topics covered here are fundamental to understanding how to efficiently load and unload Assets in Unity. Proper Asset management is crucial to keeping loading times short and memory usage low.

本章介紹Unity的序列化系統的深層内部,以及Unity如何在Unity Editor和運作時維護不同對象之間的健壯引用。它還讨論了對象和資産之間的技術差別。這裡涉及的主題是了解如何在Unity中有效加載和解除安裝資産的基礎。正确的資産管理對于縮短加載時間和降低記憶體使用率至關重要。

1.1. Inside Assets and Objects

内部資産和對象

To understand how to properly manage data in Unity, it is important to understand how Unity identifies and serializes data. The first key point is the distinction between Assets and UnityEngine.Objects. 為了了解如何在Unity中正确管理資料,了解Unity如何識别和序列化資料非常重要。第一個重點是Assets和UnityEngine.Objects之間的差別。

An Asset is a file on disk, stored in the Assets folder of a Unity project. Textures, 3D models, or audio clips are common types of Assets. Some Assets contain data in formats native to Unity, such as materials. Other Assets need to be processed into native formats, such as FBX files. 一個資産是磁盤上的檔案,存儲在Unity項目的Assets檔案夾中。紋理,3D模型或音頻剪輯是常見的資産類型。某些資産包含Unity本機格式的資料,例如材料。其他資産需要處理為本機格式,例如FBX檔案

A UnityEngine.Object, or Object with a capitalized 'O', is a set of serialized data collectively describing a specific instance of a resource. This can be any type of resource which the Unity Engine uses, such as a mesh, sprite, AudioClip or AnimationClip. All Objects are subclasses of the UnityEngine.Object base class. 一個UnityEngine.Object,或大寫“O”的對象,是一組序列化的資料統稱為一個資源(resource)的特定執行個體(instance)。這可以是Unity Engine使用的任何類型的資源,例如網格,腳本,AudioClip或AnimationClip。所有對象都是UnityEngine.Object基類的子類。

While most Object types are built-in, there are two special types. 雖然大多數對象類型都是内置的,但有兩種特殊類型。

  1. A ScriptableObject provides a convenient system for developers to define their own data types. These types can be natively serialized and deserialized by Unity, and manipulated in the Unity Editor's Inspector window.
  2. A MonoBehaviour provides a wrapper that links to a MonoScript. A MonoScript is an internal data type that Unity uses to hold a reference to a specific scripting class within a specific assembly and namespace. The MonoScript does not contain any actual executable code.

There is a one-to-many relationship between Assets and Objects; that is, any given Asset file contains one or more Objects.

一個ScriptableObject提供了一個友善的系統開發人員可以定義自己的資料類型。Unity可以對這些類型進行本機序列化和反序列化,并在Unity Editor的Inspector視窗中進行操作。

一個MonoBehaviour提供一個wrapper(包裝?)連結到一個MonoScript。MonoScript是一種内部資料類型,Unity用于儲存對特定程式集和命名空間内特定腳本類的引用。該MonoScript并沒有包含任何實際的可執行代碼。

資産和對象之間存在一對多的關系; 也就是說,任何給定的Asset檔案都包含一個或多個Objects

1.2. Inter-Object references

對象間引用

All UnityEngine.Objects can have references to other UnityEngine.Objects. These other Objects may reside within the same Asset file, or may be imported from other Asset files. For example, a material Object usually has one or more references to texture Objects. These texture Objects are generally imported from one or more texture Asset files (such as PNGs or JPGs). 所有UnityEngine.Objects都可以引用其他UnityEngine.Objects。這些其他對象可以駐留在同一資産檔案中,也可以從其他資産檔案導入。例如,材質Object通常具有一個或多個對紋理對象的引用。這些紋理對象通常從一個或多個紋理資源檔案(例如PNG或JPG)導入。

When serialized, these references consist of two separate pieces of data: a File GUID and a Local ID. The File GUID identifies the Asset file where the target resource is stored. A locally unique(1) Local ID identifies each Object within an Asset file because an Asset file may contain multiple Objects. 序列化時,這些引用由兩個單獨的資料組成:File GUID和Local ID。檔案GUID辨別存儲目标資源的資産檔案。一個本地唯一Local ID辨別資産檔案中的每個對象,因為資産檔案可能包含多個對象。

File GUIDs are stored in .meta files. These .meta files are generated when Unity first imports an Asset, and are stored in the same directory as the Asset. 檔案GUID存儲在.meta檔案中。這些.meta檔案是在Unity首次導入資産時生成的,并存儲在與資産相同的目錄中。

The above identification and referencing system can be seen in a text editor: create a fresh Unity project and change its Editor Settings to expose Visible Meta Files and to serialize Assets as text. Create a material and import a texture into the project. Assign the material to a cube in the scene and save the scene. 可以在文本編輯器中檢視上述辨別和引用系統:建立一個新的Unity項目并更改其編輯器設定以公開可見元檔案并将資産序列化為文本。建立材質并将紋理導入到項目中。将材質指定給場景中的立方體并儲存場景。

Using a text editor, open the .meta file associated with the material. A line labeled "guid" will appear near the top of the file. This line defines the material Asset's File GUID. To find the Local ID, open the material file in a text editor. The material Object's definition will look like this:

使用文本編輯器打開與材料關聯的.meta檔案。标有“guid”的行将出現在檔案頂部附近。此行定義材料Asset的檔案GUID。要查找本地ID,請在文本編輯器中打開材料檔案。材質Object的定義如下所示:

--- !u!21 &2100000

Material:

 serializedVersion: 3

 ... more data …

In the above example, the number preceded by an ampersand is the material's Local ID. If this material Object were located inside an Asset identified by the File GUID "abcdefg", then the material Object could be uniquely identified as the combination of the File GUID "abcdefg" and the Local ID "2100000".在上面的示例中,以&符号開頭的數字是素材的本地ID。如果此材料Object位于由檔案GUID“abcdefg”辨別的資産内,則可以将材料Object唯一辨別為檔案GUID“abcdefg”和本地ID“2100000”的組合。

1.3. Why File GUIDs and Local IDs?

Why is Unity's File GUID and Local ID system necessary? The answer is robustness and to provide a flexible, platform-independent workflow.

The File GUID provides an abstraction of a file's specific location. As long as a specific File GUID can be associated with a specific file, that file's location on disk becomes irrelevant. The file can be freely moved without having to update all Objects referring to the file.

As any given Asset file may contain (or produce via import) multiple UnityEngine.Object resources, a Local ID is required to unambiguously distinguish each distinct Object.

If the File GUID associated with an Asset file is lost, then references to all Objects in that Asset file will also be lost. This is why it is important that the .meta files must remain stored with the same file names and in the same folders as their associated Asset files. Note that Unity will regenerate deleted or misplaced .meta files.

The Unity Editor has a map of specific file paths to known File GUIDs. A map entry is recorded whenever an Asset is loaded or imported. The map entry links the Asset's specific path to the Asset's File GUID. If the Unity Editor is open when a .meta file goes missing and the Asset's path does not change, the Editor can ensure that the Asset retains the same File GUID.

If the .meta file is lost while the Unity Editor is closed, or the Asset's path changes without the .meta file moving along with the Asset, then all references to Objects within that Asset will be broken.

1.4. Composite Assets and importers

As mentioned in the Inside Assets and Objects section, non-native Asset types must be imported into Unity. This is done via an asset importer. While these importers are usually invoked automatically, they are also exposed to scripts via the AssetImporter API. For example, the TextureImporter API provides access to the settings used when importing individual texture Assets, such as PNG files.

The result of the import process is one or more UnityEngine.Objects. These are visible in the Unity Editor as multiple sub-assets within the parent Asset, such as multiple sprites nested beneath a texture Asset that has been imported as a sprite atlas. Each of these Objects will share a File GUID as their source data is stored within the same Asset file. They will be distinguished within the imported texture Asset by a Local ID.

The import process converts source Assets into formats suitable for the target platform selected in the Unity Editor. The import process can include a number of heavyweight operations, such as texture compression. As this is often a time-consuming process, imported Asset are cached in the Library folder, eliminating the need to re-import Assets again on the next Editor launch.

Specifically, the results of the import process are stored in a folder named for the first two digits of the Asset's File GUID. This folder is stored inside the Library/metadata/ folder. The individual Objects from the Asset are serialized into a single binary file that has a name identical to the Asset's File GUID.

This process applies to all Assets, not just non-native Assets. Native assets do not require lengthy conversion processes or re-serialization.

1.5. Serialization and instances

While File GUIDs and Local IDs are robust, GUID comparisons are slow and a more performant system is needed at runtime. Unity internally maintains a cache(2) that translates File GUIDs and Local IDs into simple, session-unique integers. These are called Instance IDs, and are assigned in a simple, monotonically-increasing order when new Objects are registered with the cache.

The cache maintains mappings between a given Instance ID, File GUID and Local ID defining the location of the Object's source data, and the instance of the Object in memory (if any). This allows UnityEngine.Objects to robustly maintain references to each other. Resolving an Instance ID reference can quickly return the loaded Object represented by the Instance ID. If the target Object is not yet loaded, the File GUID and Local ID can be resolved to the Object's source data, allowing Unity to load the object just-in-time.

At startup, the Instance ID cache is initialized with data for all Objects immediately required by the project (i.e., referenced in built Scenes), as well as all Objects contained in the Resources folder. Additional entries are added to the cache when new assets are imported at runtime(3) and when Objects are loaded from AssetBundles. Instance ID entries are only removed from the cache when an AssetBundle providing access to a specific File GUID and Local ID is unloaded. When this occurs, the mapping between the Instance ID, its File GUID and Local ID are deleted to conserve memory. If the AssetBundle is re-loaded, a new Instance ID will be created for each Object loaded from the re-loaded AssetBundle.

For a deeper discussion of the implications of unloading AssetBundles, see the Managing Loaded Assets section in the AssetBundle Usage Patterns article.

On specific platforms, certain events can force Objects out of memory. For example, graphical Assets can be unloaded from graphics memory on iOS when an app is suspended. If these Objects originated in an AssetBundle that has been unloaded, Unity will be unable to reload the source data for the Objects. Any extant references to these Objects will also be invalid. In the preceding example, the scene may appear to have invisible meshes or magenta textures.

Implementation note: At runtime, the above control flow is not literally accurate. Comparing File GUIDs and Local IDs at runtime would not be sufficiently performant during heavy loading operations. When building a Unity project, the File GUIDs and Local IDs are deterministically mapped into a simpler format. However, the concept remains identical, and thinking in terms of File GUIDs and Local IDs remains a useful analogy during runtime. This is also the reason why Asset File GUIDs cannot be queried at runtime.

1.6. MonoScripts

It is important to understand that a MonoBehaviour has a reference to a MonoScript, and MonoScripts simply contain the information needed to locate a specific script class. Neither type of Object contains the executable code of script class. 重要的是要了解MonoBehaviour具有對MonoScript的引用,而MonoScripts隻包含查找特定腳本類所需的資訊。這兩種類型的Object都不包含腳本類的可執行代碼。

A MonoScript contains three strings: assembly name, class name, and namespace.

MonoScript包含三個字元串:程式集名稱,類名稱和命名空間。

While building a project, Unity compiles all the loose script files in the Assets folder into Mono assemblies. C# scripts outside of the Plugins subfolder are placed into Assembly-CSharp.dll. Scripts within the Plugins subfolder are placed into Assembly-CSharp-firstpass.dll, and so on. In addition, Unity 2017.3 also introduces the ability to define custom managed assemblies. 建構項目時,Unity會将Assets檔案夾中的所有松散腳本檔案編譯為Mono程式集。插件子檔案夾之外的C#腳本放在Assembly-CSharp.dll中。Plugins子檔案夾中的腳本放在Assembly-CSharp-firstpass.dll中,依此類推。此外,Unity 2017.3還引入了定義自定義托管程式集的功能。

These assemblies, as well as pre-built assembly DLL files, are included in the final build of a Unity application. They are also the assemblies to which a MonoScript refers. Unlike other resources, all assemblies included in a Unity application are loaded on application start-up. 這些程式集以及預建構的程式集DLL檔案都包含在Unity應用程式的最終版本中。它們也是MonoScript引用的程式集。與其他資源不同,Unity應用程式中包含的所有程式集都在應用程式啟動時加載。

This MonoScript Object is the reason why an AssetBundle (or a Scene or a prefab) does not actually contain executable code in any of the MonoBehaviour Components in the AssetBundle, Scene or prefab. This allows different MonoBehaviours to refer to specific shared classes, even if the MonoBehaviours are in different AssetBundles.

此MonoScript對象是:AssetBundle(或場景或預制件)實際上不包含AssetBundle,Scene或預制件中的任何MonoBehaviour元件中的可執行代碼的原因。這允許不同的MonoBehaviours引用特定的共享類,即使MonoBehaviours位于不同的AssetBundle中。

1.7. Resource lifecycle

To reduce loading times and manage an application's memory footprint, it's important to understand the resource lifecycle of UnityEngine.Objects. Objects are loaded into/unloaded from memory at specific and defined times.

An Object is loaded automatically when:

The Instance ID mapped to that Object is dereferenced

The Object is currently not loaded into memory

The Object's source data can be located.

Objects can also be explicitly loaded in scripts, either by creating them or by calling a resource-loading API (e.g., AssetBundle.LoadAsset). When an Object is loaded, Unity tries to resolve any references by translating each reference's File GUID and Local ID into an Instance ID. An Object will be loaded on-demand the first time its Instance ID is dereferenced if two criteria are true:

The Instance ID references an Object that is not currently loaded

The Instance ID has a valid File GUID and Local ID registered in the cache

This generally occurs very shortly after the reference itself is loaded and resolved.

If a File GUID and Local ID do not have an Instance ID, or if an Instance ID with an unloaded Object references an invalid File GUID and Local ID, then the reference is preserved but the actual Object will not be loaded. This appears as a "(Missing)" reference in the Unity Editor. In a running application, or in the Scene View, "(Missing)" Objects will be visible in different ways, depending on their types. For example, meshes will appear to be invisible, while textures may appear to be magenta.

Objects are unloaded in three specific scenarios:

Objects are automatically unloaded when unused Asset cleanup occurs. This process is triggered automatically when scenes are changed destructively (i.e. when SceneManager.LoadScene is invoked non-additively), or when a script invokes the Resources.UnloadUnusedAssets API. This process only unloads unreferenced Objects; an Object will only be unloaded if no Mono variable holds a reference to the Object, and there are no other live Objects holding references to the Object. Furthermore, note that anything marked with HideFlags.DontUnloadUnusedAsset and HideFlags.HideAndDontSave will not be unloaded.

Objects sourced from the Resources folder can be explicitly unloaded by invoking the Resources.UnloadAsset API. The Instance ID for these Objects remains valid and will still contain a valid File GUID and LocalID entry. If any Mono variable or other Object holds a reference to an Object that is unloaded with Resources.UnloadAsset, then that Object will be reloaded as soon as any of the live references are dereferenced.

Objects sourced from AssetBundles are automatically and immediately unloaded when invoking the AssetBundle.Unload(true) API. This invalidates the File GUID and Local ID of the Object's Instance ID, and any live references to the unloaded Objects will become "(Missing)" references. From C# scripts, attempting to access methods or properties on an unloaded object will produce a NullReferenceException.

If AssetBundle.Unload(false) is called, live Objects sourced from the unloaded AssetBundle will not be destroyed, but Unity will invalidate the File GUID and Local ID references of their Instance IDs. It will be impossible for Unity to reload these Objects if they are later unloaded from memory and live references to the unloaded Objects remain. (4)

1.8. Loading large hierarchies

When serializing hierarchies of Unity GameObjects, such as during prefabs serialization, it is important to remember that the entire hierarchy will be fully serialized. That is, every GameObject and Component in the hierarchy will be individually represented in the serialized data. This has interesting impacts on the time required to load and instantiate hierarchies of GameObjects.

When creating any GameObject hierarchy, CPU time is spent in several different ways:

Reading the source data (from storage, from an AssetBundle, from another GameObject, etc.)

Setting up the parent-child relationships between the new Transforms

Instantiating the new GameObjects and Components

Awakening the new GameObjects and Components on the main thread

The latter three time costs are generally invariant regardless of whether the hierarchy is being cloned from an existing hierarchy or is being loaded from storage. However, the time to read the source data increases linearly with the number of Components and GameObjects serialized into the hierarchy, and is also multiplied by the speed of the data source.

On all current platforms, it is considerably faster to read data from elsewhere in memory rather than loading it from a storage device. Further, the performance characteristics of the available storage media vary widely between different platforms. Therefore, when loading prefabs on platforms with slow storage, the time spent reading the prefab's serialized data from storage can rapidly exceed the time spent instantiating the prefab. That is, the cost of the loading operation is bound to storage I/O time.

As mentioned before, when serializing a monolithic prefab, every GameObject and component's data is serialized separately, which may duplicate data. For example, a UI screen with 30 identical elements will have the identical element serialized 30 times, producing a large blob of binary data. At load time, the data for all of the GameObjects and Components on each one of those 30 duplicate elements must be read from disk before being transferred to the newly-instantiated Object. This file reading time is a significant contributor to the overall cost of instantiating large prefabs. Large hierarchies should be instantiated in modular chunks, and then be stitched together at runtime.

Unity 5.4 note: Unity 5.4 altered the representation of transforms in memory. Each root transform's entire child hierarchy is stored in compact, contiguous regions of memory. When instantiating new GameObjects that will be instantly reparented into another hierarchy, consider using the new GameObject.Instantiate overloaded variants which accept a parent argument. Using this overload avoids the allocation of a root transform hierarchy for the new GameObject. In tests, this speeds up the time required for an instantiate operation by about 5-10%.

2.The Resources folder

2.1. Best Practices for the Resources System

資源系統

Don't use it.

不要使用它。

這個強烈的建議有幾個原因:

This strong recommendation is made for several reasons:

Use of the Resources folder makes fine-grained memory management more difficult使用Resources檔案夾會使細粒度的記憶體管理變得更加困難

Improper use of Resources folders will increase application startup time and the length of builds

-As the number of Resources folders increases, management of the Assets within those folders becomes very difficult

資源檔案夾使用不當會增加應用程式啟動時間和建構時間

随着資源檔案夾數量的增加,對這些檔案夾中的資産(Assets)的管理變得非常困難

The Resources system degrades a project's ability to deliver custom content to specific platforms and eliminates the possibility of incremental content upgrades

-AssetBundle Variants are Unity's primary tool for adjusting content on a per-device basis

資源系統降低了項目向特定平台提供自定義内容的能力,并消除了增量内容更新的可能性

AssetBundle Variants是Unity基于每個裝置調整内容的主要工具

2.2. Proper uses of the Resources system

正确使用資源系統

There are two specific use cases where the Resources system can be helpful without impeding good development practices: 有兩個特定用例,其中資源系統可以提供幫助,而不會妨礙良好的開發實踐:

1. The ease of the Resources folder makes it an excellent system to rapidly prototype. However, when a project moves into full production, the use of the Resources folder should be eliminated. Resources檔案夾的簡易性使其成為快速原型的優秀系統。但是,當項目進入完全生産階段時,應該消除Resources檔案夾的使用。

2. The Resources folder may be useful in some trivial cases, if the content is:在一些簡單的情況下,Resources檔案夾可能很有用:

Generally required throughout a project's lifetime

Not memory-intensive

Not prone to patching, or does not vary across platforms or devices

Used for minimal bootstrapping

通常在整個項目的生命周期中都需要

不是記憶體密集型的

不容易修補,或者不會跨平台或裝置變化

用于最小的自舉

Examples of this second case include MonoBehaviour singletons used to host prefabs, or ScriptableObjects containing third-party configuration data, such as a Facebook App ID. 第二種情況的示例包括用于托管預制件的MonoBehaviour單例,或包含第三方配置資料的ScriptableObject,例如Facebook App ID。

2.3. Serialization of Resources

The Assets and Objects in all folders named "Resources" are combined into a single serialized file when a project is built. This file also contains metadata and indexing information, similar to an AssetBundle. As described in the AssetBundle documentation, this index includes a serialized lookup tree that is used to resolve a given Object's name into its appropriate File GUID and Local ID. It is also used to locate the Object at a specific byte offset in the serialized file's body.

在建構項目時,名為“Resources”的所有檔案夾中的Assets和Objects将合并為一個序列化檔案。此檔案還包含中繼資料和索引資訊,類似于AssetBundle。如AssetBundle文檔中所述,此索引包括一個序列化查找樹,用于将給定Object的名稱解析為其相應的File GUID和Local ID。它還用于在序列化檔案正文中的特定位元組偏移處定位Object。

On most platforms, the lookup data structure is a balanced search tree, which has a construction time that grows at an O(n log(n)) rate. This growth also causes the index's loading time to grow more-than-linearly as the number of Objects in Resources folders increases.

在大多數平台上,查找資料結構是平衡搜尋樹,其構造時間以O(n log(n))速率增長。随着Resources檔案夾中對象數量的增加,這種增長也會導緻索引的加載時間增長超過線性。

This operation is unskippable and occurs at application startup time while the initial non-interactive splash screen is displayed. Initializing a Resources system containing 10,000 assets has been observed to consume multiple seconds on low-end mobile devices, even though most of the Objects contained in Resources folders are rarely actually needed to load into an application's first scene.

此操作是不可映射的,并且在應用程式啟動時發生,同時顯示初始非互動式啟動螢幕。已經觀察到初始化包含10,000個資産的資源系統在低端移動裝置上消耗多秒,即使資源檔案夾中包含的大多數對象實際上很少需要加載到應用程式的第一個場景中。

3.AssetBundle fundamentals

本章讨論AssetBundles。它介紹了建構AssetBundle的基本系統,以及用于與AssetBundles互動的核心API。特别是,它讨論了AssetBundles本身的加載和解除安裝,以及AssetBundles中特定Asset和Objects的加載和解除安裝。

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.

3.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.

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.

AssetBundle系統提供了存儲一個或多個檔案的方法,用一種以Unity可以索引和序列化的存檔格式。AssetBundles是Unity在安裝後傳遞和更新非代碼内容的主要工具。這允許開發人員送出較小的應用程式包,最小化運作時記憶體壓力,并有選擇地加載針對最終使用者裝置優化的内容。

了解AssetBundles的工作方式對于為移動裝置建構成功的Unity項目至關重要。有關AssetBundle内容的總體描述,請檢視AssetBundle文檔。

3.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的資訊,例如其辨別符,壓縮類型和清單。清單是一個由Object名稱辨別的查找表。每個實體(entry)都提供一個位元組索引,訓示在AssetBundle的資料段中可以找到給定Object的位置。在大多數平台上,此查找表實作為平衡搜尋樹。具體來說,Windows和OSX派生的平台(包括iOS)使用紅黑樹。是以,随着AssetBundle内資産數量的增加,建構清單所需的時間将增加超過線性。

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中的資産生成的原始資料。如果将LZMA指定為壓縮方案,則會壓縮所有序列化資産的完整位元組數組。如果指定了LZ4,則單獨壓縮單獨Assets的位元組。如果未使用壓縮,則資料段将保留為原始位元組流。

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中單獨壓縮對象。是以,如果訓示5.3之前的Unity版本從壓縮的AssetBundle讀取一個或多個對象,則Unity必須解壓縮整個AssetBundle。通常,Unity會緩存AssetBundle的解壓縮副本,以提高同一AssetBundle上後續加載請求的加載性能。

3.3. Loading AssetBundles

AssetBundles can be loaded via four distinct APIs. The behavior of these four APIs is different depending on two criteria:

AssetBundles可以通過四個不同的API加載。這四種API的行為因兩個标準而異:

  1. Whether the AssetBundle is LZMA compressed, LZ4 compressed or uncompressed

AssetBundle是否為LZMA壓縮,LZ4是壓縮還是未壓縮

2.The platform on which the AssetBundle is being loaded正在加載AssetBundle的平台

These APIs are: 這些API是:

AssetBundle.LoadFromMemory(Async optional異步可選)

AssetBundle.LoadFromFile(Async optional異步可選)

UnityWebRequest's DownloadHandlerAssetBundle

WWW.LoadFromCacheOrDownload (on Unity 5.6 or older在Unity 5.6或更早版本上)

3.3.1 AssetBundle.LoadFromMemory(Async)

Unity's recommendation is not to use this API. 建議不要使用此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壓縮的AssetBundles将逐字複制。

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。它的功能沒有改變。

3.3.2.AssetBundle.LoadFromFile(異步)

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)或取消引用其InstanceID時,AssetBundle的對象将按需加載。在這種情況下,不會消耗多餘的記憶體。在Unity Editor中,API會将整個AssetBundle加載到記憶體中,就像從磁盤讀取位元組并使用AssetBundle.LoadFromMemoryAsync一樣。如果在Unity Editor中對項目進行了分析,則此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 chapter

注意:在使用Unity 5.3或更早版本的Android裝置上,嘗試從Streaming Assets路徑加載AssetBundle時,此API将失敗。Unity 5.4中已解決此問題。有關更多詳細資訊,請參閱AssetBundle使用模式一章中的分發 - 随項目一起提供的部分。(該部分為這個教程的最後一章)

Prior to Unity 5.3, this API was known as AssetBundle.CreateFromFile. Its functionality has not been changed.

3.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 call UnityWebRequest.GetAssetBundle.

該UnityWebRequest API允許開發人員指定統一究竟應該如何處理下載下傳的資料,并允許開發者以消除不必要的記憶體使用情況。使用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緩存,具體取決于下載下傳處理程式的配置方式。所有這些操作都在本機代碼中進行,進而消除了擴充托管堆的風險。此外,該下載下傳處理程式并沒有儲存所有下載下傳的位元組的本機代碼副本,進一步降低了下載下傳的AssetBundle的記憶體開銷。

LZMA-compressed AssetBundles will be decompressed during download and cached using LZ4 compression. This behavior may be changed by setting Caching.CompressionEnabled.

LZMA壓縮的AssetBundles将在下載下傳期間解壓縮并使用LZ4壓縮進行緩存。可以通過設定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. 當下載下傳完成後,Download Handler 的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對象提供緩存資訊,并且Unity緩存中已存在所請求的AssetBundle,那麼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響應代碼和标頭。

3.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.

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.

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 the Asset assignment strategies section in the AssetBundle 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 occurring simultaneously.

3.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.

通常,應盡可能使用AssetBundle.LoadFromFile。在速度,磁盤使用和運作時記憶體使用方面,此API是最有效的。

For projects that must download or patch AssetBundles, it is strongly recommended to use UnityWebRequest for projects using Unity 5.3 or newer, and WWW.LoadFromCacheOrDownload for projects using Unity 5.2 or older. As detailed in the Distribution section of the next chapter, it is possible to prime the AssetBundle Cache with Bundles included within a project's installer.

對于必須下載下傳或更新檔AssetBundles項目,強烈建議使用UnityWebRequest在Unity 5.3或更高版本,以及項目WWW.LoadFromCacheOrDownload在Unity 5.2或以上的項目。如下一章的“ 分發”部分所述,可以使用項目安裝程式中包含的Bundle來填充AssetBundle Cache。

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.

使用UnityWebRequest *或* WWW.LoadFromCacheOrDownload時,請確定在加載AssetBundle後下載下傳程式代碼正确調用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 chapter for more details.

對于需要具有獨特,特定緩存或下載下傳要求的大量工程團隊的項目,可以考慮使用自定義下載下傳程式。編寫自定義下載下傳程式是一項非常重要的工程任務,任何自定義下載下傳程式都應與AssetBundle.LoadFromFile相容。有關更多詳細資訊,請參閱下一章的“ 分發”部分。

3.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從AssetBundles加載,這些API都附加到AssetBundle對象,它們具有同步和異步變體:

  • LoadAsset (LoadAssetAsync)
  • LoadAllAssets (LoadAllAssetsAsync)
  • LoadAssetWithSubAssets(LoadAssetWithSubAssetsAsync)

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 the Low-level loading details section for the underlying technical reasons for this behavior. 異步負載将每幀加載多個對象,直到其時間片限制。有關此行為的基本技術原因,請參閱低級加載詳細資訊部分。(下一節)

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.

LoadAllAssets應該加載多個獨立UnityEngine.Objects時使用。它隻應在需要加載AssetBundle中的大多數或所有對象時使用。與其他兩個API相比,LoadAllAssets比對LoadAssets的多個單獨調用稍快。是以,如果要加載的資産數量很大,但是一次隻需要加載少于66%的AssetBundle,請考慮将AssetBundle拆分為多個較小的包并使用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,例如具有嵌入動畫的FBX模型或嵌入了多個腳本的腳本集。如果需要加載的對象全部來自同一資産,但存儲在帶有許多其他無關對象的AssetBundle中,則使用此API。

For any other case, use LoadAsset or LoadAssetAsync. 其他情況,LoadAsset或LoadAssetAsync

3.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加載是在主線程上執行的:從工作線程的存儲中讀取Object的資料。任何不接觸Unity系統的線程敏感部分(腳本,圖形)的東西都将在工作線程上轉換。例如,VBO将從網格建立,紋理将被解壓縮等。

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開始,對象加載已經并行化。多個對象在工作線程上反序列化,處理和內建。當Object完成加載時,将調用其Awake回調,并且Object将在下一幀對Unity Engine的其餘部分可用。

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每幀最多50毫秒

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 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開始,加載多個對象,直到達到對象加載的幀時間限制。假設所有其他因素相等,資産加載API的異步變體将始終比同類的同步版本更長,因為發出異步調用和引擎可用的對象之間的最小一幀延遲。

3.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.

AssetBundles之間的依賴關系使用兩個不同的API自動跟蹤,具體取決于運作時環境。在Unity Editor中,可以通過AssetDatabase API 查詢AssetBundle依賴項。可以通過AssetImporter API 通路和更改AssetBundle配置設定(assignments)和依賴項。在運作時,Unity提供了一個可選API,用于通過基于ScriptableObject的AssetBundleManifest API 加載在AssetBundle建構期間生成的依賴關系資訊。

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 the Inter-Object references section of the Assets, Objects and Serialization article.

當一個或多個父AssetBundle的UnityEngine.Object引用一個或多個其他AssetBundle的UnityEngine.Object時,AssetBundle依賴于另一個AssetBundle。有關對象間引用的更多資訊,請參閱“ 資産,對象和序列化”一文的“ 對象間引用”部分。

As described in the Serialization and instances section of that article, AssetBundles serve as sources for the source data identified by the FileGUID & LocalID of each Object contained within the AssetBundle. 如該文章的序列化和執行個體部分所述,AssetBundles充當由AssetBundle中包含的每個Object的FileGUID和LocalID辨別的源資料的源。

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.

因為在首次取消引用其執行個體ID時加載了Object,并且因為在加載AssetBundle時為Object配置設定了有效的執行個體ID,是以AssetBundle(之間)的加載順序并不重要。相反,在加載Object本身之前加載包含Object依賴關系的所有AssetBundle非常重要。加載父AssetBundle時,Unity不會嘗試自動加載任何子AssetBundle。

Example:

Assume material A refers to texture B. Material A is packaged into AssetBundle 1, and texture B is packaged into AssetBundle 2. 假設材料A引用組織B。材料A打包到AssetBundle 1中,紋理B打包到AssetBundle 2中。

In this use case, AssetBundle 2 must be loaded prior to loading Material A out of AssetBundle 1.

在此用例中,必須在從AssetBundle 1加載材料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 1之前加載AssetBundle 2,或者必須從AssetBundle 2顯式加載Texture B.在從MaterialBundle 1加載材料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.

有關AssetBundle依賴關系的更多資訊,請參閱手冊頁。

3.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建構管道(pipeline)時,Unity會序列化包含每個AssetBundle依賴項資訊的Object。此資料存儲在單獨的AssetBundle中,該AssetBundle包含AssetBundleManifest類型的單個Object。

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.

此資産将存儲在AssetBundle中,其名稱與建構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,用于列出與清單同時建構的所有AssetBundle,以及兩種查詢特定AssetBundle依賴關系的方法:

1.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的直接子節點,子節點子節點等的依賴關系。

2.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.

請注意,這兩個API都配置設定字元串數組。是以,它們應該隻是謹慎使用,而不是在應用程式生命周期的性能敏感部分使用。

3.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.

在許多情況下,最好在玩家進入應用程式的性能關鍵區域(例如主遊戲級别或世界)之前加載盡可能多的所需對象。這在移動平台上尤其重要,因為移動平台對本地存儲的通路速度很慢,并且在運作(互動)時加載和解除安裝對象的記憶體流失可以觸發垃圾收集器。

For projects that must load and unload Objects while the application is interactive, see the Managing loaded assets section of the AssetBundle usage patterns article for more information on unloading Objects and AssetBundles.

對于必須在應用程式互動時加載和解除安裝對象的項目,請參閱AssetBundle使用模式文章的管理已加載資源部分,以擷取有關解除安裝對象和AssetBundle的更多資訊。

4.AssetBundle usage patterns

This chapter discusses problems and potential solutions to various aspects of using AssetBundles in practice. 本系列的前一章介紹了AssetBundles的基礎知識,其中包括各種加載API的底層行為。本章讨論在實踐中使用AssetBundle的各個方面的問題和可能的解決方案。

4.1Managing loaded Assets

管理已加載的資産