🎄

Unity Addressables Tips 〜2021年に於けるアップデート情報を添えて〜

2021/12/15に公開

はじめに

この記事は Unity Advent Calendar 2021 の 15日目 の投稿です。
14日目は @tsubaki_t1 さんの「Unity 2021.2のSceneViewで色々な操作を行う新機能、Overlayについて」でした。
これまでは頑張って EditorWindow とか作ったりしないと実現しづらかった拡張を SceneView に重ねられるようになるのはかなり便利そうですね!折を見て試してみようと思います!

さて、本稿では「Addressables Tips」と称して、2021年6月にオンライン開催された Unity 道場 2021.1登壇した際の Tips を一部再編しつつ本稿執筆時点での最新情報も交えて(@monry の観測範囲内に於ける)Addressables Tips を紹介したいと思います。

動作検証などは Unity 2021.2.6f1, Addressables 1.19.14 にて行っています。

Addressables Tips

開発・本番とで Catalog や AssetBundle のダウンロード先 URL を切り替える

※本項は Unity 道場 2021.1 の登壇内容に含まれます。

実際のゲーム開発の現場では、開発ビルドと本番ビルドとで Addressables のダウンロード先 URL を切り替える運用をしたくなることがよくあります。

ビルド時に Profile を切り替えることで URL を変更することも可能ですが、Addressables v1.13.1 から追加された「ID transform function」という機能を用いれば、ランタイムで Catalog や AssetBundle のダウンロード先を書き換えることが可能になります。

Addressables.ResourceManager.InternalIdTransformFunc というプロパティに IResourceLocation を引数に取り string を返すメソッドや匿名関数などを設定することで、ランタイムで InternalId (Address を示す URL などの値)を参照する際に設定した処理が呼ばれて、戻り値の string が実際の InternalId として利用されるようになります。

次のサンプルコードは、「Profile の RemoteLoadPath などに本番用の URL が設定されている」ことを前提にして、「開発ビルドの場合はホスト名を置換する」といった処理になります。

Addressables.ResourceManager.InternalIdTransformFunc += (resourceLocation) =>
{
    if (!Debug.isDebugBuild)
    {
        return resourceLocation.InternalId;
    }
    return resourceLocation.InternalId.Replace(
        "assets.monry.jp",
        "assets.dev.monry.jp"
    );
};

なお、この機能を用いれば、ホスト名の置換だけでなく「端末スペックに応じた Addressble Group とか Asset の差し替え」も可能っちゃ可能です。
が、参照差し替え用のコンポーネントを用意する必要があったりして、Addressables の機能のみを用いて AssetBundle Variants 的なコトを実現するのは難しそうです。
「こうすれば出来るよー」みたいなアイディアをお持ちの方は是非教えてください! :pray:

AssetBundle Variants の模倣を検証した際の簡単なログはコチラ
  • Material から HD の Texture を参照しておく
  • SD / HD の切り替えを行うためのアセットを管理する Group を作成
    • Bundle Mode を Packad Separately にする
    • AssetBundle CRC を Disabled にする
  • InternalIdTransformFunc で resourceLocation.InternalId.Replace("hd/", "sd/") 的な処理をする
  • Editor 検証時は Addressables ビルドしつつ Play Mode Script: Use Existing Build にする
  • 再生!
    • 本来ならココで HD のテクスチャが SD に差し替わるコトを期待するも、テクスチャ読み込まれず
    • Material が持つテクスチャの GUID が別のモノになるから NG?
    • ランタイムで SD を Addressables.LoadAssetAsync() しようとしても AsyncOperationHandle が使用中と言われるので、Load 自体は出来てる?

Player ビルドの前に Addressables をビルドする

Addressables 1.19.4 で Player ビルド時に Addressables もビルド できるオプションが追加されました。

Added options for building Addressables content as a prebuild step when building Player.

これまでは、Addressables ビルド時に生成される link.xml を Player に同梱する必要がある場合、事前に生成しておくか IPreprocessBuildWithReport を実装したエディタスクリプトを書く必要がありましたが、このオプションを用いればその手間を省くことができます。

このオプションは、AddressableAssetSettings.asset のインスペクタで設定します。

Use global Settings を選択した場合は環境設定に追加されている同様のオプションの選択状態に準じます。

Asset の読み込み方を Group 単位に設定する

Addressables 1.18.11 に Asset Load Mode というオプションが追加されました。

デフォルトは Requested Asset and Dependencies ですが、All Assets and Dependencies にすることで、Group 内の全ての Asset を読み込むコトができるようになります。
あまり使いどころはないかも知れませんが、シーン内で同一 Group に含まれる Sprite を多数読み込む場合などに、パフォーマンス的にやや有利になるものと思われます。

ダウンロード済の古い AssetBundle キャッシュをクリアする

Addressables 1.19.4 に Addressables.CleanBundleCache() という API が追加されました。
このメソッドは、端末に保持されている Catalog から参照されていない古い AssetBundle のキャッシュをクリアすることができます。
引数に Catalog ID(IResourceLocator.LocatorId から取得可能)のリストを渡すと、該当する Catalog から参照されなくなった AssetBundle を消してくれるっぽいです。(未検証)

なお、丸っとドゥーン!(全てのキャッシュを破棄)したい場合は Caching.ClearCache() を使うと良いようです。

Note, that only AssetBundles loaded through UnityWebRequest are cached. If you want to purge the entire cache, use Caching.ClearCache instead. In the Editor CleanBundleCache should only be called when using the "Use Existing Build (requires built groups)" playmode script as it loads content from bundles.

内部で利用される UnityWebRequest の挙動を上書きする

Addressables 1.19.4 から Addressables 内部で利用される UnityWebRequest の挙動を上書きするコトが出来るようになりました。
Addressables.WebRequestOverride というプロパティに Action<UnityWebRequest> を設定することで実現できます。

このデリゲートが設定されていれば、Addressables が UnityWebRequest.SendWebRequest() を実行する前に呼び出してくれるので、「Authorization: Bearer ... を付けたい!」とか「GET じゃなくて POST にしたい!」とかの細かい調整ができるようになります。
また、UnityWebRequest.downloadHandlerDownloadHandlerAssetBundleDownloadHandlerBuffer(Catalog の場合はコッチ)が設定済の状態でデリゲートが呼び出されますが、コレを丸ごと自作の DownloadHandler で上書きするコトも可能です。

Load Path / Build Path をセットで定義する

Addressables 1.18.9 で Path Pair という概念が導入され、Load Path / Build Path のセットを定義することが出来るようになりました。
Profile 管理ウィンドウの Create ボタンから Build and Load path variables (All Profiles) を選択すると、専用の入力フォームが表示されるので Build / Load の両パスを設定します。


次のスクリーンショット画像はデフォルトの LocalBuildPath, LocalLoadPath, RemoteBuildPath, RemoteLoadPath を模倣したものになります。

各 Path Pair の右に表示されているプルダウンは AssetBundle の置き場所のプリセットです。

  • Built-in: プロジェクトルート以下の固定のパスが設定される
  • Editor Hosted: Editor がホストするサーバの IP とポートが設定される
  • Cloud Content Delivery: Unity Cloud Content Delivery (docs) の URL などが設定される(要 Services 設定)
  • Custom: 自前で設定する

の中から選択できます。

設定した Path Pair は、Catalog や Group の設定時に利用可能です。

おわりに

2021年に於ける Addressables の最新情報を Tips という形でまとめてみました。
個人的に気になった機能追加とかを中心にまとめているので、やや薄味なアドカレになってしまっているかも知れませんが、ご容赦いただけると幸いです😅

明日の Unity Advent Calendar 2021@Nitudon さんの「Unity2021についてなにか」です。

Discussion