Version: 2023.1
言語: 日本語
アセットバンドルにパッチを適用する
アセットバンドルのダウンロードの整合性とセキュリティ

トラブルシューティング

Tips for Investigating AssetBundle Build results

The following methods can be useful for collecting information after an AssetBundle build has run. These can be useful when investigating unexpected behavior, or when tuning the assignment of assets to bundles.

Logs

The Unity Editor log collects information during a build, such as warning or error messages. And at the end of an AssetBundle build there is a detailed message logged that shows information about the type and size breakdown for each AssetBundle.

Build Report

AssetBundle builds generate a BuildReport which is a Unity SerializedFile written to Library/LastBuild.buildreport inside the project directory. This file is useful for seeing a summary of the timings for build steps and a detailed view of the contents of the AssetBundle. The BuildReport API can be used to read information from the BuildReport file.

Two unsupported tools are available for viewing the content of the BuildReport:

.manifest files

The manifest files generated alongside each AssetBundle give some human-readable details about the contents of an AssetBundle.

Clean Builds

To speed up iteration time Unity supports incremental building for AssetBundles. For example, elements from past builds can be reused for aspects of the project that have not changed since the last build. While this can speed up iteration time, there are a few limitations on its ability to detect changes in the input, especially if scripts run by build callbacks are changing data in a non-deterministic way. Therefore, you should always perform a clean build rather than an incremental build when you are building an official release of your AssetBundles.

The BuildAssetBundleOptions.ForceRebuildAssetBundle flag, passed as an option to BuildPipeline.BuildAssetBundles(), is the recommended way to perform a clean build.

In some rare cases it might also be desirable to erase the Library/ShaderCache directory. This cache is not flushed when BuildAssetBundleOptions.ForceRebuildAssetBundle is specified. On many projects the Shader compilation phase can be quite a time consuming step, so erasing the cache can add a lot of time to the next Player or AssetBundle build.

Alternatively, the most reliable way to perform a completely clean build is to stop Unity, erase the project’s Library directory, and then restart Unity. This can be very time consuming because all the project Assets need to be reimported and other data is regenerated.

Examining AssetBundle contents

In some cases you might want to look directly inside an AssetBundle, or compare the contents of two AssetBundles.

The Unity Editor installation includes the WebExtract and Binary2Text executables. You can use WebExtract to extract the files that are nested inside the AssetBundle, similar to extracting a zip file. Then you can use Binary2Text to produce a text format dump of the contents of a binary SerializedFile. Its output is somewhat similar to the yaml format used by Unity.

Another similar mechanism to see the content of an AssetBundle’s SerializedFiles in text form is to run UnityDataTools with its “dump” argument.

The raw content of Serialized files tends to be very technical and very large, especially when Shaders or Meshes or binary data is present. But these dumps can also provide a wealth of information if you can narrow down a problem to specific objects within a file. Comparing the extracted content of two similar AssetBundles using a diff tool can be a convenient way to narrow down the precise differences.

Target Switching

The arguments to the BuildPipeline.BuildAssetBundles API lets you specify the target (and subtarget) platform where you will be deploying the AssetBundles.

It is possible the requested platform is different from what is currently configured on the Build Settings dialog. However you should always make sure the settings in the Build Settings match the settings for your AssetBundle build, prior to triggering your build script. When the targets don’t match, Unity must recompile the Editor scripts to reflect the new platform and also potentially trigger imports for Assets like textures that have platform specific representations. Then at the end of the build it will restore the state back to match the original target platform. Typically this works fine, but it can add significant time to each build, which can add up when performing a lot of build iterations. Furthermore the script that contains the call to BuildPipeline.BuildAssetBundles will continue to execute in the script domain as compiled for the current target, not the specified build target. This is only a problem if the build script, or callback scripts, expects platform-specific code or assemblies to be available. For many projects this subtle difference will not be an issue. But to help avoid this sort of pitfall you should always make sure that any code executed during a build checks the target dynamically (e.g. with if statements) instead of using platform conditional compilation (#ifdef statements).

For command line builds the --buildTarget command line argument should be used to match the target you want to build.

Asset Duplication

Unity のアセットバンドル システムは、オブジェクトがアセットバンドルにビルドされる際に、そのオブジェクトの全ての依存を特定します。これは アセットデータベースによって行われます。この依存情報は、そのアセットバンドルに含まれる一揃いのオブジェクトを特定するために使用されます。

アセットバンドルへの割り当てはアセットレベルで行われます。アセットバンドルに明示的に割り当てられたアセット内のオブジェクトは、その 1 つのアセットバンドルにのみビルドされます。BuildPipeline.BuildAssetBundles のどのシグネチャを呼び出すかによって、アセットの AssetImporter.assetBundleName プロパティに空でない文字列を設定するか、AssetBundleBuild.assetNames に列挙することでアセットが “明示的に割り当て” られます。

アセットバンドルで明示的に割り当てられないアセットの一部であるオブジェクトは、それを参照するオブジェクトを含む各アセットバンドルに含まれます。

つまり、 2 つのことなるオブジェクトが 2 tsの異なるアセットバンドルに割り当てられていて、その両方が共通の依存関係オブジェクトへの参照を持つ場合、その依存関係オブジェクトは両方のアセットバンドルにコピーされます。重複した依存関係は、インスタンス化も行なわれます。つまり、依存関係オブジェクトの 2 つのコピーが異なる識別子を持つ異なるオブジェクトと認識されます。その結果、アプリケーションの アセットバンドルの合計サイズが大きくなります。また、アプリケーションがその オブジェクトの両方の親をロードする場合は、オブジェクトの 2 つの異なるコピーがメモリーにロードされることになります。

この問題の解決方法はいくつかあります。

  1. 異なるアセットバンドル内にビルドされた複数のオブジェクトが依存を共有しないようにする。依存を共有するオブジェクトは、その依存を重複させることなく同じアセットバンドル内に配置することができます。

    • この方法は通常、依存の共有が多いプロジェクトには適していません。再ビルドや再ダウンロードが過剰な頻度で必要なモノリシックなアセットバンドルが出来てしまい、効率性が損なわれる可能性があります。
  2. 同じ依存を共有する複数のアセットバンドルが同時に読み込まれないようにアセットバンドルを分類する。

    • この方法は、レベルベースのゲームなど特定の種類のプロジェクトで役立ち得ます。ただし、オブジェクトが複製されるとビルド時間とプロジェクトのアセットバンドルのサイズが増加し、ロードする時間に影響を与える可能性があるため、依然として代わりに妥協しなければならない点があります。
  3. 全ての依存アセットが、その所属するアセットバンドル内に確実にビルドされるようにする。これによりアセットの重複が起きる可能性は無くなりますが、複雑な状況が発生します。アプリケーションは、異なるアセットバンドル間における依存をトラッキングし、 AssetBundle.LoadAsset APIs の呼び出しが行われる前に正しいアセットバンドルが確実に読み込まれようにしなければなりません。

オブジェクトの依存関係は、UnityEditor 名前空間にある AssetDatabase API を介して追跡されます。名前空間が示唆するように、この API は Unity エディターでのみ利用可能で、ランタイムでは利用できません。AssetDatabase.GetDependencies を使用すると、特定のオブジェクトまたはアセットの直下の依存関係をすべて見つけることができます。これらの依存関係は、それ自体の依存関係を持つ可能性があるため、再帰的な計算になる可能性があることに注意してください。 アセットバンドルへのアセットの割り当ては、BuildPipeline.BuildAssetBundles を呼び出す際に AssetBundleBuild 構造体の配列を渡して明示的に定義するか、AssetImporter API を使用して問い合わせることができます。アセットバンドルの直接的または間接的な依存関係がすべてアセットバンドルに割り当てられていることを確認したり、アセットバンドルに割り当てられていない依存関係を 2 つのアセットバンドルが共有しないことを確認したりするエディタースクリプトを記述できます。

ノート: Addressables パッケージを使用してアセットバンドルをビルドする場合、Addressables Analyze ウィンドウを使用して、重複するアセットを見つけることができます。

Sprite Atlas Duplication

以下のセクションでは、 アセット依存の計算コードを自動生成のスプライトアトラスと併用した場合に起こる特異な現象について解説します。

自動生成されたスプライトアトラスは全て、その生成元のスプライトオブジェクトが含まれるアセットバンドルに割り当てられます。スプライトオブジェクトが複数のアセットバンドルに割り当てられる場合、そのスプライトアトラスは単一のアセットバンドルに割り当てられるのではなく、複製されます。スプライトオブジェクトがアセットバンドルに割り当てられていない場合、そのスプライトアトラスも、アセットバンドルに割り当てられません。

スプライトアトラスの複製を確実に防ぐためには、同じスプライトアトラスにタグ付けされた全てのスプライトが、確実に同じアセットバンドルに割り当てられるようにしてください。

Android Textures

Due to heavy device fragmentation in the Android ecosystem, it’s often necessary to compress textures into several different formats. While all Android devices support ETC1, ETC1 doesn’t support textures with alpha channels.

To use AssetBundle Variants, all textures that can’t be cleanly compressed using ETC1 must be isolated into texture-only AssetBundles. Next, create sufficient variants of these AssetBundles to support the non-ETC2-capable slices of the Android ecosystem, using vendor-specific texture compression formats such as DXT5, PVRTC. For each AssetBundle Variant, change the included textures’ TextureImporter settings to the compression format appropriate to the Variant.

ランタイムでは、各種テクスチャ圧縮形式への対応は SystemInfo.SupportsTextureFormat API で判定できます。この情報は、対応された形式で圧縮されたテクスチャを含む AssetBundle Variant の選択と読み込みに使用されます。

Android のテクスチャ圧縮形式についての詳しい情報は こちらを参照してください。。

Interactions between Shaders and AssetBundles

アセットバンドルをビルドすると、Unity はそのバンドル内の情報を使用して、コンパイルするシェーダーバリアントを選択します。これには、アセットバンドル内のシーン、マテリアル、Graphics SettingsShaderVariantCollections に関する情報が含まれます。

別々のビルドパイプラインは、他のパイプラインから独立して独自のシェーダーをコンパイルします。プレイヤービルドと Addressable ビルドの両方がシェーダーを参照する場合、Unity はシェーダーの 2 つの別個のコピーを各パイプラインに 1 つずつコンパイルします。

この処理では、キーワード、テクスチャ、コード実行による変更などのランタイム情報は考慮されません。特定のシェーダーをビルドに加えたい場合は、必要なシェーダーを含む ShaderVariantCollection を加えるか、グラフィックス設定の Always Included Shaders リストに加えて手動でシェーダーをビルドに入れます。

アセットバンドルにパッチを適用する
アセットバンドルのダウンロードの整合性とセキュリティ