UnityのAddressablesを使ってサーバーにあるアセットバンドルを使う

今回はUnityのAddressablesについて見ていきたいと思います。

Addressablesについてはわたくしが自身のゲームをWebGL形式として出力した時の事を元にしているので、アセットバンドルを置いておくサーバーの種類や設定、Unity、Addressablesのバージョン等によってエラーが発生する可能性があります。

この記事ではプラットフォームをWindows、Mac、Linuxの設定にしてWindowsで動作確認をしています。

また全てのプラットフォーム向けではなかったり、全ての機能について書いてもいません。

なので、個人的な備忘録程度の記事とお考え下さい。(^_^;)

Addressablesについての詳しい情報はUnityのマニュアルやこの記事の最後に記載している参考サイトを参照してください。

スポンサーリンク

Addressablesとは

Addressablesは旧AssetBundleの後継機能でUnityのアセットをアドレスに登録してローカルやリモート上にファイル(アセットバンドルファイル)として持っておいて、必要に応じてメモリにロードとアンロードをしたり管理する機能です。

ローカルかリモートかはグループでの設定によって切り替えることが出来ます。

Addressablesを使用するとアセットバンドルをサーバー等に置いておいてゲームで使用するときにロードをして使用することが出来るので、追加のコンテンツの配信で全部のゲームを再度読み込む必要はなく該当するファイルの更新だけをすることが出来ます。

アップデートも該当するアセットバンドルを専用のアップデートビルドを行いファイルを差し替えるだけで簡単に出来ます。

Addressablesのインポート

Addressablesをテストする際は新しいプロジェクトを作成して試す方が混乱を避けられるので良いと思います。

ということで、今回はUnity2021.2.7f1を使用して新しいプロジェクトを作成し、Addressablesは1.19.17をインストールして使用しています。

プロジェクトが出来たらPackage Managerを使ってAddressablesをインストールします。

UnityメニューのWindowからPackage Managerを選択して開きます。

パッケージの種類をUnity Registryにし、Addressablesの1.19.17をインストールします。

Addressablesをインストールする為にUnityRegistryに変更する

Addressables1.19.17をインストールする

Addressablesを使ってみる

Addressablesのインストールが出来たのでAddressablesを使っていきます。

次にAddressablesのGroupを開いてAddressablesの設定ファイルを作成します。

UnityメニューのWindowからAsset Management→Addressables→Groupsを選択します。

Addressables関係のウインドウはここのAddressablesから開けます。

Addressablesの設定ファイルを作成する為にGroupウインドウを開く

Groupsを選択するとGroupsウインドウが開きますが、Addressablesの設定ファイルを作成していない為、作成するボタンが表示されます。

Create Addressables Settingsボタンを押して設定ファイルを作成します。

Addressablesの設定ファイルを作成する

設定ファイルが作成されるとグループ名にBuilt In Data、Default Local Group(Default)というグループが既に作成されているのを確認出来ます。

設定ファイルはAssetsフォルダのAddressableAssetDataフォルダの中に作成されます。

Group

Groupはアセットをグループ分けするためのものです。

試しにアセットを作成してグループに追加してみます。

適当にシーンを作成し、そこに3D ObjectのCubeとSphereを作成します。

AssetsフォルダにPrefabsフォルダを作成し、そこにシーンのヒエラルキーからCubeとSphereをPrefabsフォルダにドラッグ&ドロップしてプレハブにします。

CubeプレハブやSphereプレハブを選択し、インスペクタを見ると見慣れないAddressableというチェック項目が増えているのを確認することが出来ます。

インスペクタにAddressable項目が出現した

CubeプレハブのインスペクタのAddressableにチェックを入れてみます。

インスペクタのAddressable項目にチェックを入れてみる

するとAddressables GroupsウインドウのDefault Local Group(Default)グループにCubeプレハブが追加されます。

Default Local Group(Default)にアセットが追加された

グループへのアセットの登録はAddressables GroupsウインドウのグループにAssetsフォルダから直接アセットをドラッグ&ドロップすることでも出来ます。

Assets/Prefabs/SphereプレハブをAddressables GroupsのDefault Local Group(Default)グループにドラッグ&ドロップして追加してみます。

SphereプレハブをAddressables Groupsウインドウのグループにドラッグ&ドロップして追加する

Default Local Group(Default)にSphereプレハブが追加されました。

Sphereプレハブがグループに追加された

グループの移動

Default Local Group(Default)はデフォルトで作られるグループなので自分で新しいグループを作成し、そこに先ほどDefault Local Group(Default)に登録したアセットを移動してみることにします。

Addressables GroupsウインドウのCreateからGroups→Packed Assetsを選択します。

Blankを選択するとスキーマが設定されず自身で項目を追加する必要があるので選択しません。

Addressablesの新しいグループを作成する

新しくPacked Assetsという名前のグループが作成されました。

新しいAddressablesのグループが作成された

Packed Assetsグループを選択し、F2キーを押すか右クリックからRenameを選択し、名前をMyGroupとします。

現時点ではDefault Local Groupグループの右に(Default)という表記があり、アセットのインスペクタでAddressableのチェックを入れると自動でDefault Local Groupに追加されています。

そこでMyGroupをデフォルトのグループに変更します。

MyGroupを選択した状態で右クリックからSet As Defaultを選択します。

自分で作ったグループをデフォルトにする

これでデフォルトのグループがMyGroupになりました。

自分で作ったグループがデフォルトになった

Default Local GroupからMyGroupにCubeプレハブとSphereプレハブを移動します。

Addressables GroupsウインドウのDefault Local GroupにあるCubeとSphereを選択し、MyGroupにドラッグ&ドロップします。

これでグループの移動が出来ました。

MyGroupにCubeとSphereが移動された

グループの設定

簡易的ですがグループの設定を見ていきます。

Addressables GroupsウインドウのMyGroupを選択し、インスペクタを見るとグループの設定を見ることが出来ます。

Addressablesのグループの設定項目

Active Profile: DefaultとなっているのはデフォルトのDefaultプロファイルを使用している為です。

右のInspect Top Level Settingsボタンを押すとAddressable Assetの設定項目へと移動出来ます。

これはAssets/AddressableAssetsDataフォルダのAddressableAssetSettingsをインスペクタに表示しただけです。

Content Packing & Loadingを見ていきます。

Build & Load Path

Build & Load PathsではLocalとRemoteを切り替える事が出来ます。

Localはローカル環境のビルドとロードの設定で、Remoteはサーバー等を介して利用するリモート環境のビルドとロードの設定です。

Build Pathのパスにビルド、Load Pathのパスからロードします。

現時点ではBuild & Load PathsはLocalになっていると思いますが、Build PathではライブラリへのビルドでLoad Pathも同様です。

この場合は外部ファイルではなく内部にアセットバンドルが含まれる形になると思います。

Advanced Options

Advanced Optionsの項目について見ていきます。

Asset Bundle Compression

Asset Bundle Compressionはアセットバンドルの圧縮形式で、LZ4、LZMA、Uncompressed(圧縮しない)を選択することが出来ます。

LZMAはLZ4よりもファイルサイズが小さくなりCDN(コンテンツ配信ネットワーク)の場合の奨励設定となっていますが、わたくしがWebGL形式で使った所エラーとなる為、場合によってはLZ4圧縮を使用する必要があります。

Include in Buildはこのグループのアセットをビルドに含めるかどうかです。ゲームのテストだけで使用するアセットグループ等の場合はチェックを外します。

Force Unique ProviderはAddressablesがこのグループのリソースプロバイダークラスの一意のインスタンスを使用するかどうかです。グループ間でインスタンスを共有したくないものはチェックを外します。

Use AssetBundle Cacheはリモートで分散されたアセットバンドルをキャッシュするかどうかです。

Asset Bundle CRCはロードする前にバンドルの整合性を検証するかどうかです。Disableはしない、Enabled,Including Cachedはキャッシュされたものを含んで検証、Enabled,Excluding Cacheはキャッシュを除いたものを検証します。

Use UnityWebRequest for Local Asset Bundlesはローカルアセットバンドルの読み込み時にAssetBundle.LoadFromFileAsyncの代わりにUnityWebRequestAssetBundle.GetAssetBundleを使用するかどうかです。

Request Timeoutはリモートのアセットバンドルをダウンロードする時のタイムアウト間隔です。

Use Http Chunked Transferはアセットバンドルをダウンロードする時にHttp/1.1チャンク転送エンコーディング方式を使用するかどうかです。Unity2019.3以降は非奨励になります。

Http Redirect Limitはアセットバンドルをダウンロードする時に許可されるリダイレクトの数です。制限なしの場合は-1を設定します。

Retry Countはアセットバンドルのダウンロードに失敗した時に再試行する回数です。

Include Addresses in Catalogはカタログにアドレス文字列を含めるかどうかで、アドレス文字列を使用してグループ内のアセットをロードしない場合はチェックを外してカタログのサイズを縮小出来ます。

Include GUIDs in CatalogはカタログにGUID文字列を含めるかどうかです。AssetReferencesやGUID文字列を使用してグループ内のアセットをロードしない場合はチェックを外すことでカタログサイズを縮小することが出来ます。

Include Labels in Catalogはカタログにラベル文字列を含めるかどうかです。ラベルを使用してグループ内のアセットをロードしない場合はチェックを外すことでカタログサイズを縮小することが出来ます。

Internal Asset Naming Modeは内部のアセットの命名方法です。FullPath(パス)、FileName(ファイル名)、GUID(GUID文字列)、Dynamic(グループ内のアセットを元にした最小単位の名前)

Internal Bundle Id Modeはアセットバンドルの内部IDを作成する方法です。Group Guidでグループ名とアセットバンドルGUID文字列を組み合わせてバンドルIDを作成するようです。他の設定はわかりません・・・、デフォルトのGroup Guid Project Id Hashのままでいいかな・・・(^_^;)

Cache Clear Behaviourはアプリケーションがいつアセットバンドルのキャッシュをクリアするかどうかです。Clear When Space is Needed In Cacheはキャッシュに空きが必要な時、Clear When New Version Loadedは新しいバージョンがロードされた時。

Bundle Modeはアセットバンドルをまとめる方法です。Pack Togetherはすべてのアセットを単一にまとめてアセットバンドルを作成します。Pack Separatelyはグループ内のプライマリアセットごとにアセットバンドルを作成します。Pack Together By Labelはラベルごとにまとめてアセットバンドルを作成します。

Bundle Naming Modeはアセットバンドルのファイル名の設定方法です。Filenameはそのままファイル名にします。Append Hash to Filenameはファイル名にハッシュ値を付けてファイル名にします。Use Hash of AssetBundleはアセットバンドルをハッシュ値にしてファイル名とします。Use Hash of Filenameはファイル名をハッシュ値にしてファイル名とします。

Bundle Naming Modeの設定によってはエラーが発生するのでエラーが出たらデフォルトの設定のままか、ハッシュ値を使用しないFilenameの設定にするといいかもしれません。

Asset Load Modeはアセットの読み込む方法で、Requested Asset And Dependenciesはリクエストしたアセットと依存しているアセットを読み込み、All Packed Assets And Dependenciesはグループ全てのアセットと依存しているアセットを読み込みます。

Asset Providerはアセットバンドルからアセットをロードするために使用するプロバイダーを設定します。
色々設定がありますが、デフォルトのAssetBundle Providerのままでよさそうです。

Content Update Restriction

Update Restrictionはアセットバンドルを更新する際の制限の設定です。

Can Change Post Releaseはリリース後に変更が可能、Cannot Change Post Releaseはリリース後の変更は不可です。

どちらにしても「以前のビルドの更新」アセットバンドルの更新は出来るようですが、

Can Change Post Releaseはアセットバンドル内のアセットが更新された場合にバンドル全体が再構築され、
Cannot Change Post Releaseはアセットバンドル内のアセットが更新された場合に更新用に作成された新しいグループを作成し移動させ、既存のバンドルにあるバージョンを上書きします。

Can Change Post Releaseは頻繁に更新する小さいアセットバンドルに使用し、
Cannot Change Post Releaseは更新する必要のないアセットバンドルや大規模なアセットバンドルに使用します。

ローカルロードパスからロードする予定のグループはCannot Change Post Releaseに設定する必要があるようです。こうすることでグループのアセットを変更した場合にのみ変更するアセットをダウンロードするようになります。

Profile

Profileはビルドファイルの出力先、ビルドファイルの読み込み先を指定する設定です。

UnityメニューのWindowからAsset Management→Addressables→Profilesを選択し、Addressables Profilesウインドウを開きます。

デフォルトではDefaultプロファイルが作成されています。

AddressablesのProfilesウインドウ

DefaultのLocalはBuilt-InとなっておりLocal.BuildPathとLocal.LoadPathともにローカル設定になっています。これはアセットバンドルをビルドに含めて、そこからロードすることになります。

また先ほど作ったMyGroupグループでのBuild & Load PathsでLocalと設定していたのでDefaultプロファイルのLocalの設定を使ってビルドとロードをすることになっています。

DefaultプロファイルのRemoteの設定ではEditor HostedがされておりRemote.BuildPathはServerData/[BuildTarget]、Remote.LoadPathはhttp://[PrivateIpAddress]:[HostingServicePort]となっています。

[変数名]という表記で実際には別の物に置き換えられます。

[BuildTarget]はBuildTargetに書いてあるUnityメニューのFile→Build Settingsで指定したターゲットプラットフォーム。
[PrivateIpAddress]はプライベートIPアドレス。
[HostingServicePort]は使用するポート番号。

にそれぞれ置き換えられます。

Editor Hostedはエディターでリモートを確認する為の設定で、ビルドファイルはプロジェクトフォルダのServerDataフォルダの中にUnityメニューのFile→Build Settingsで設定しているビルドのターゲットプラットフォーム([BuildTarget]の部分)に応じたフォルダに作成されます。

Build SettingsでWindws,Mac,Linux設定にしている場合はプロジェクト名/ServerData/StandaloneWindows64の中にアセットバンドルのビルドファイルが作成されます。

Remote.LoadPathがhttp://[PrivateIpAddress]:[HostingServicePort]となっている為、エディターで実行した時に自身のプライベートIPアドレスとポートを使ってエディター上でリモートのアセットバンドルの確認をすることが出来ます。

自前のプロファイルを作成する

Defaultプロファイルを使ってローカルとリモートのテストをすることが出来ますが、サーバー等にアセットバンドルをアップロードし、それを利用する時用の自前のプロファイルを作成します。

Addressables ProfilesウインドウのCreateからProfileを選択します。

自前のAddressablesのプロファイルを作成する

新しく出来たプロファイルを選択し、F2キーを押すか右クリックからRenameを選択し、名前をRemoteProfileとします。

現時点ではサーバー上にアセットバンドルを置かずにやるのでRemoteProfileはただ作ってみただけです。

後でサーバー上のアセットバンドルを使ったサンプルを作りますのでそれまではDefaultプロファイルを使っていきます。

Addressablesのサンプルを作ってみる

Addressablesについて見てきたので、とりあえずサンプルを作ってみましょう。

サンプルを作る過程でAddressablesの使い方についてもやっていきます。

アセットバンドルから読み込んでインスタンス化する

まずはAddressablesのMyGroupに登録したCubeプレハブとSphereプレハブをリモート環境にアップロードしたアセットバンドルからロードし、それをインスタンス化するということをやっていきます。

今回の場合はリモートといってもローカル上にアセットバンドルファイルをビルドしたものから、Unityエディター上でアセットバンドルをロードし、それをインスタンス化します。

アセットのインスタンス化について

Addressablesのアセットをインスタンス化するやり方には

LoadAssetAsyncでロードしてからObject.Instantiateを使ってインスタンス化
Addressables.InstantiateAsyncを使ってインスタンス化

の方法があります。

LoadAssetAsyncでロードしたオブジェクトをObject.Instantiateでインスタンス化する場合はアセットの参照カウントは最初に読み込んだ1回だけになります。

Addressables.InstantiateAsyncを使って複数回インスタンス化した場合はその分だけ参照カウントが増えていきます。

Addressablesのアセットをロードした場合はアセットをロード時に使用したハンドルを使って必ず解放(Addressables.Release等を使う)する必要があり、解放すると参照カウントが減り、参照カウントが0になるとメモリからアセットが解放されます。

メモリの参照カウント等はAddressablesのEvent Viewerを使うと実行時に確認することが出来ます。

Event Viewer

アセットの参照カウントやメモリの状態に関してはEvent Viewerで確認することが出来ます。

Event Viewerを使用するにはAddressable Asset SettingsのSend Profiler Eventsにチェックを入れる必要があります。

UnityメニューのWindowからAsset Management→Addressables→Groupでウインドウを開き、MyGroupを選択したら、インスペクタのInspect Top Level Settingsボタンを押し、DiagnosticsのSend Profiler Eventsにチェックを入れます。

もしくはAssets/AddressableAssetsDataを選択し、同様に設定出来ます。

Send Profiler Eventsにチェックを入れる

Event ViewerはUnityメニューのWindowからAsset Management→Addressables→Event Viewerを選択してウインドウを開きます。

MyGroupをRemoteに変える

今回のサンプルはアセットバンドルをアプリケーションに同梱させるのではなく別ファイルとしてビルドするので、MyGroupグループのBuild & Load PathsをLocalからRemoteに変更する必要があります。

UnityメニューのWindowからAsset Management→Addressables→Groupを選択し、Addressables Groupウインドウを開き、MyGroupを選択してインスペクタのBuild & Load PathsをRemoteに変更します。

MyGroupのBuild&Load PathsをRemoteに変更する

Remoteに変更するとBuild PathとLoad Pathが変更されます。

エディターで実行出来るようにホスティングを有効にする

ローカル上にアセットバンドルファイルがあってもサーバーを介して実行しているかのようにする為、ホスティングを有効にします。

UnityメニューのWindowからAsset Management→Addressables→Hostingを選択し、Addressables Hostingウインドウを開きます。

CreateからLocal Hostingを選択します。

Local Hostingの作成

Local Hosting 0を選択し、Enableにチェックを入れローカルホスティングを有効にします。

ローカルホスティングを有効にする

Enableにチェックを入れられない場合はPortに指定されている番号が既に使用されている可能性があるので、その場合は数字を変えてEnableにチェックを入れます。

これでローカルホスティングが有効になりました。

Addressablesに登録したプレハブをロードしインスタンス化するスクリプト

Addressablesに登録したプレハブをロードし、インスタンス化するスクリプトを作成します。

LoadAssetAsyncとGameObject.Instantiateを使った場合

スクリプトは適当に何らかのゲームオブジェクトに取り付けます。

Addressablesにしたプレハブのロードをする為にAssetReference型のcubePrefabフィールドとAssetReferenceGameObject型のspherePrefabフィールドを作成します。

AssetReferenceなんちゃらはGameObjectだったり、Spriteだったり特定の型に限定することも出来ますので、今回はひとつだけAssetReferenceGameObjectにしました。

AsyncOperationHandleはAddressablesのアセットをロードする際のハンドルとして使います。

これらのハンドルは使用が終わったら解放します。

loadCubePrefabとloadSpherePrefabはAddressablesのアセットをロードした結果のゲームオブジェクトを入れておくフィールドで、これらからゲームオブジェクトをインスタンス化します。

StartメソッドではAddressables.LoadAsyncを使ってAddressablesにしたcubePrefabをロードし、読み込みが終わったら中括弧の中の処理を実行します。

ロード後のハンドルobjをcubePrefabHandleに保持し、ロードしたアセット(obj.Result)をloadCubePrefabに保持します。

またインスタンス化したゲームオブジェクトをリストに入れておきます。

その後loadCubePrefabを2回インスタンス化しています。

その後spherePrefabのLoadAssetAsyncを使ってspherePrefabをロードし、終わったらLoadedメソッドを実行するようにします。

書き方が違うだけでcubePrefabをロードし、インスタンス化したのと変わりません。

Invokeを使って10秒後にDeleteメソッドを実行します。

Loadedメソッドではハンドルのステータスが成功していたらそのハンドルとアセットの保持をし、2回インスタンス化し、リストに保持しています。

DeleteメソッドではCubeとSphereそれぞれのインスタンスを削除し、リストをクリアした後にAddressables.ReleaseInstanceとAddressables.Releaseを使って各ハンドルを解放しています。

ゲームオブジェクトに取り付けたInstantiateAddressablesPrefabスクリプトのインスペクタでcubePrefabにCubeプレハブ、spherePrefabにSphereプレハブをそれぞれ設定します。

InstantiateAddressablesPrefabのcubePrefabとspherePrefabに設定する

spherePrefabはAssetReferenceGameObject型に指定しているのでゲームオブジェクトだけを設定出来ます。

アセットバンドルをビルドする

Groupへのアセットの登録、アセットをロードしてインスタンス化するスクリプトの作成とゲームオブジェクトの取り付けが出来たので、ビルドをしエディター上で確認してみます。

(注)その前にUnityメニューのFile→Build SettingsのプラットフォームでWindows,Mac,Linuxが選択されているとします。

Addressables Groupウインドウを開き、Build→New Build→Default Build Scriptを選択し、ビルドを実行します。

Addressablesのビルドを行う

少し前にMyGroupグループのBuild & Load PathsをRemoteに変えているのでBuild PathはServerData/StandaloneWindows64等となっているはずです(OSがWindowsなら)。

なので、ビルドされたファイルはUnityのこのプロジェクトが保存されているフォルダ(Windowsならデフォルトだとドキュメントの中にプロジェクトのフォルダがあるかもしれない)の中にServerDataというフォルダが出来その中にさらにStandaloneWindows64フォルダが作成され、その中にファイルが作成されます。

Addressablesのファイルの保存先

これでビルドが出来たので次はローカルに出力したファイルをエディター上で読み取るという設定に変更する必要があります。

Addressables GroupウインドウのPlay Mode ScriptでUse Existing Buildを選択します。

AddressablesのプレイモードをUse Existing Buildに変更する

Use Asset Databaseはエディターのアセットから直接ロードして実行します。
Simulate Groupsはアセットバンドルを作成せずにアセットバンドルを介してロードされたかのようにResourceManagerを介してエディター上のアセットをロードします。
Use Existing Buildはアセットバンドルから実際にロードします。

プラットフォームがWebGL形式の場合にUse Existing Buildを選択すると音声ファイルがなんちゃらというエラーが出て実行できなかったので、エディター上でなくアプリケーションを出力し、そこから直接実行して試す等したほうがいいかもしれません。

Unityエディターのプレイボタンを押して確認していきますが、Addressables HostingのEnableのチェックをするのを忘れないでください(外れていると実行できません)。

Unityを実行して確認するとCubeとSphereが2つずつ生成され10秒後に消えます。

Event Viewerを確認するとCubeとSphereが2つずつインスタンス化されている時は参照カウントがそれぞれ1となっています。

LoadAssetAsyncとObject.Instantiateを使った場合のEvent Viewer

InstantiateAsyncを使った場合

次にAddressables.InstantiateAsyncを使った場合の例です。

処理はSphereプレハブを使っていないだけで同じなので説明は割愛します。

InstantiateAsyncの場合はインスタンス化されると参照カウントが増えていくので、インスタンス化されたゲームオブジェクト個々にゲームオブジェクトが削除されたらAddressables.Releaseを使って解放することにします。

Cubeプレハブに以下のスクリプトを作成し取り付けます。

OnDestroyはこのスクリプトが取り付けられたゲームオブジェクトが削除される時に呼ばれるので、その時に自身のゲームオブジェクトを解放します。

先ほどビルドしたファイル(プロジェクトフォルダ/ServerData/StandaloneWindows64フォルダの中身)を削除し、Addressables GroupウインドウのBuild→Clean Build→Allを選択します。

AddressablesのClean Buildを実行する

これを行ったのはテストの為に一からやる為です。

Clean Buildが終わったらBuildからNew Build→Default Build Scriptを選択しビルドします。

実行してみるとEvent Viewerでは以下のようにCubeプレハブの参照カウントが2となっています。

InstantiateAsyncを使った場合のCubeの参照カウント

サーバー上にアセットバンドルファイルをアップし実行してみる

Unityエディター上で実行することが出来たので、次はアセットバンドルファイルをサーバー上にアップロードしてそこからアセットを読み込むことにします。

サーバーは提供しているサービスと契約するか無料サービスを利用してください。(._.)

わたくしはブログをロリポップサーバーに置いているので、そこにファイルをアップロードして確認しています。

プロファイルを変更する

UnityメニューのWindowからAsset Management→Addressables→Profilesを選択し、Addressables Profilesウインドウを開きます。

少し前に作ったRemoteProfileプロファイルを選択し、右クリックからSet Activeを選択します。

RemoteProfileをデフォルトにする

次にRemotProfileのEditor Hostedとなっている部分をCustomに変更します。

さらにRemote.LoadPathをサーバーのアセットバンドルファイルがあるフォルダまでのパスに変更します。

Remote.LoadPathをサーバー上のURLに変更する

わたくしの場合は

https://gametukurikata.com/アセットバンドルファイルがあるフォルダまでのパス

という形になります。

[BuildTarget]の部分はStandaloneWindows64に置き換えられます。

これでプロファイルの変更が出来ました。

次にアセットを更新する際に必要になるのでAssets/AddressableAssetsDataを選択し、インスペクタでBuild Remote Catalogにチェックを入れます。

Build Remote Catalogにチェックを入れる

ローカルのStandaloneWindows64にあるファイルを削除し、Addressables GroupsウインドウのBuildからClean Build→Allを選択し、その後Build→New Build→Default Build Sciptを選択し、ビルドします。

ビルドが完了したらStandaloneWindows64フォルダ事さきほどプロファイルで指定したURLの場所にアップロードします。

次にUnityメニューのFileからBuild SettingsでScene In Buildに先ほどのサンプルを設定したシーンをドラッグ&ドロップします。

そしてBuildかBuild And Runボタンを押し、スタンドアロンアプリケーションを開いてUnityエディター上と同じように実行されるかを確認します。

Cubeが表示され消えるという動作が実行出来ればサーバー上のアセットバンドルから読み込みが成功したということになります。

アセットを更新してみる

サーバー上に置いたアセットバンドルファイルからアセットを読み込むことが出来たので、次はアセットの更新をしてみたいと思います。

UnityエディターのAssetsフォルダで右クリックからCreate→Materialを選択して名前をRedとし、Albedo右の色を赤色に変更してCubeプレハブのMaterialsのElement0にRedマテリアルを設定します。

今回はアセットバンドルの更新をするのでClean Buildは実行しません。

次にAddressables GroupsウインドウのBuildからUpdate a Previous Buildを選択し、ファイル選択ウインドウが出たらaddressables_content_state.binというファイルを選択して開きます(最初に開いたフォルダの中でWindowsならWindowsの中にある)。

Update a Previous Buildを選択する

addressables_content_state.binファイルを開く

アップデートビルドが実行されるとStandaloneWindows64フォルダには追加でファイルが作られます。

Addressablesのアップデートビルド

新しく出来たファイルをサーバー上の先ほどアセットバンドルファイルをアップロードしたのと同じフォルダにアップロードし、スタンドアロンのアプリケーションを実行するとCubeが赤色になっているのを確認出来ます。

StandaloneWindows64フォルダ内のファイルを全てサーバー上にアップロードしてもOKです。

もし更新されていなければ最初のビルドからやり直してください。

最初のアセットバンドルのビルド→アプリケーションのビルド→更新したアセットバンドルのビルド

という流れになります。

シーンの読み込みサンプル

次にシーンの読み込みとダウンロードのプログレスバーの作成をしたいと思います。

シーンの読み込みに関しては現在のシーンに別のシーンを追加し、他のシーンへ移動する時は現在のシーンをアンロードして新しいシーンを追加する方法で、Titleシーンを読み込むと以下のような感じで、

LoaderシーンにTitleシーンを追加したイメージ

Stage1シーンを追加する時はTitleシーンをアンロードしてStage1シーンをロードするという感じになります。

LoaderシーンにStage1シーンを追加したイメージ

もう一つのやり方としては、シーンを読み込むスクリプトを取り付けたゲームオブジェクトを常に読み込んだシーンに残して常に1つのシーンのみ存在するようにする方法があります。

Loaderシーンはなく、今のシーンに変えて別のシーンをロードするという感じです。

シーンを入れ替えるイメージ

今回は他のシーンを読み込むだけのLoaderシーンを作成し、そこに新たなシーンを追加するやり方で作ってみます。

サンプルを作成すると以下のような感じになります。

シーン切り替え時の処理は改善する必要があるかもしれません。

Loaderシーンの作成

他のシーンを読み込むだけのシーンをLoaderという名前で作成します。

Loaderシーンのヒエラルキーで右クリックからCreate Emptyを選択し、名前をLoaderとします。

Loaderスクリプトを作成し、Loaderゲームオブジェクトに取り付けます。

sceneは遷移するシーンをリストで設定出来るようにしています。

previousSceneは他のシーンを読み込む時に前のシーンをアンロードする必要がありますが、そのシーンを保持しておくためのものです。

downloadSizeHandleはダウンロードするアセットバンドルの操作をする時に使用するハンドルです。

downloadDependenciesHandleはダウンロードするアセットに依存するアセットのダウンロードに使用するハンドルです。

sceneAssetReferenceはシーンを読み込む時に使用します。

unloadはシーンをアンロードするかどうかのフラグです。

loaderCanvasはロード状況を伝えるUIのCanvasを設定します。

downloadSliderはダウンロード状況を表すスライダーを設定します。

downloadPercentTextはダウンロードが何%終わったかを表示するテキストを設定します。

loaderSceneCameraはLoaderシーンのメインカメラを設定します。

StartメソッドではloaderSceneCameraにメインカメラを設定します。

次にLoadSceneメソッドの引数にTitleという文字列を渡して呼び出します。

if文でアクティブなシーンがLoaderの時だけ実行するようにしていますが、ずっとアクティブなシーンはLoaderになるのでこの条件はいらないかもしれません。(^_^;)

LoadSceneメソッドでは受け取った文字列をフィールドのloadSceneNameに保持しておきます。

unloadがtrueの時はアンロードするべきシーンがあるので、Addressables.UnloadSceneAsyncを使用してpreviousSceneをアンロードします。

アンロードが終了したらOnSceneUnloadメソッドを実行します。

その後、コルーチンを使ってLoadingメソッドを実行します。

Loadingメソッドでは引数で受け取った文字列によってsceneAssetReferenceに該当するシーンを入れます。

Addressables.GetDownloadSizeAsyncを使ってロードするシーンのダウンロードサイズのハンドルを作成します。

それが終わったらダウンロードサイズが0.95より小さい時にloaderCanvasを有効化します。

これはダウンロードしたアセットバンドルがキャッシュされ新たにダウンロードする必要がそれほど必要ない場合に毎回ローディング画像が表示されてしまうのを防ぐ為です。

この処理はリモートで使うとうまくいかないので別の方法を考える必要があります。(^_^;)

次にAddressables.DownloadDependenciesAsyncを使ってダウンロードするアセットに依存するものをダウンロードするハンドルを作成します。

そのステータスがNoneである場合(成功か失敗ではないので進行している状態)だけdownloadSliderとdownloadPercentTextに現在のダウンロード状況を表示します。

LoadSceneAsyncを使って新たなシーンをロードしますが、LoadSceneMode.Additiveを指定して現在のシーン(Loader)に新たに追加するようにしています。

ロードが終わったらOnSceneLoadedメソッドを実行します。

ここら辺の読み込みに関しては、UnityLearningMaterialsの動画を参考にさせて頂きました。

https://learning.unity3d.jp/2272/

その他UnityのAddressablesのマニュアルも参考になります。

Preloading dependencies | Addressables | 1.19.19

OnSceneLoadedメソッドでは引数で受け取ったハンドルのステータスが成功だった場合にpreviousSceneにobj.Resultを入れます。

シーンがロードに成功したのでunloadにtrueを入れ、次のシーンを読み込む時にこのシーンをアンロードすることになります。

シーンの読み込みが終わったらローディングの進捗を表示しているloaderCanvasとLoaderシーンにあるカメラのloaderSceneCameraを無効にします。

Loaderシーンのカメラが有効であると他のシーンに影響がある為です。

次にAddressables.Releaseを使って使用したハンドルを解放しています。

OnSceneUnLoadedメソッドはシーンのアンロードが終わった時に呼び出されるので成功していたらunloadをfalseにしてアンロードすべきシーンがなくなったこととします。

previousSceneには空のシーンインスタンスを入れておきます。

シーンのアンロードが終わったら次のシーンを読み込んでいる時の進捗を見えるようにする必要がある為、loaderSceneCameraを有効にしています。

Loaderゲームオブジェクトを選択し、右クリックからUI→Panelを選択し、名前をBacgroundとし、ローディング中の背景とします。

BackgroundのAnchorでstretch stretchを選択し、ウインドウ幅に応じてサイズが変わるようにします。

さらにLoaderゲームオブジェクトを選択し、右クリックからUI→Sliderを選択して作成します。

Sliderの子のFill AreaのLeftとRightを0、その子のFillのWidthを0としSliderの値と見た目が一致するようにします。

Sliderの子のHandle Slide Areaは使わないので選択してDeleteキーを押し削除します。

さらにSliderを選択した状態から右クリック→Legacy→Textを選択して作成します。

今回は昔のTextを使っていますがTextMeshProのTextを使ってももちろん構いません。

このTextは何%ダウンロードが完了したかの数値を入れるテキストにします。

Loaderシーンのヒエラルキーは以下のようになりました。

Loaderシーンのヒエラルキー

他のシーンの作成

Loaderスクリプトを記述する前に他のシーンを作成していきます。

Titleシーンを作成します。

Titleシーンのヒエラルキーで右クリックからUI→Legacy→Buttonを選択し、名前をButton1とします。

Button1を選択し、Ctrl+Dキーを押して複製し、名前をButton2とします。

Button1の子のTextにはStage1、Button2の子のTextにはStage2と記入し、ボタンを押したらそのシーンへと移動しますということを表します。

実際にはボタンが押された時にLoaderスクリプト内の処理を実行するようにスクリプトからリスナーを取り付けます。

今回はLoaderシーンにTitleシーンを追加するという形になるので、Titleシーンに作られたEventSystemは不要となるのでTitleシーンのEventSystemゲームオブジェクトは削除しておきます。

次にCanvasにButtonScriptという名前のスクリプトを作成し取り付けます。

ボタンが押された時にシーンを遷移する処理が書かれているLoaderスクリプトの処理を実行させる必要があるんですが、LoaderスクリプトはTitleシーン内にはないのでシーンが読み込まれた時にLoaderスクリプトを取得し、ボタンが押されたらその処理を実行するという形にする必要があります。

なので、スクリプトからボタンが押された時のリスナーを取り付けます。

SceneNameは列挙型で各シーンで自分がどのシーンなのかを手動で設定するようにします。

button1とbutton2は自身(Canvas)の子から名前で検索し、Buttonコンポーネントを取得し設定します。

sceneNameによってボタンが押された時に実行する処理が変わってくるので、ボタンのonClickにAddListenerを使ってボタンが押された時に実行する処理を変えています。

Titleシーンのヒエラルキーは以下のようになりました。

Titleシーンのヒエラルキー

TitleシーンのヒエラルキーのCanvasを選択し、インスペクタのButtonScriptを以下のように設定します。

TitleシーンのButtonScriptの設定

AssetsフォルダにあるTitleシーンを選択し、Ctrl+Dキーを押して複製し、名前をStage1とします。

同じようにもうひとつ複製し、名前をStage2とします。

Stage1とStage2シーンそれぞれのCanvasのインスペクタのButtonScriptでsceneNameを各シーンと同じものを設定します。

また各シーンでは別のシーンへと遷移するボタンなのでButton1とButton2の子のTextを変えどのシーンに遷移するかをわかりやすくしておきます。

次にLoaderシーンに戻りLoaderスクリプトの設定をしていきます。

LoaderシーンのLoaderスクリプトの設定

Loaderのsceneの数値を3にし、上からTitle、Stage1、Stage2と設定します。

これはスクリプトで指定したものと関係するので順序は間違えないでください。

loaderCanvas、downloadSlider、downloadPercentTextには該当するものをそれぞれ設定します。

実行する前の準備

これで機能が出来たので後はシーンをAddressablesに登録します。

Titleシーン、Stage1シーン、Stage2シーンの各インスペクタでAddressablesにチェックを入れます。

MyGroupがデフォルトグループとなっている為、MyGroupに各シーンが追加されます。

MyGroupにシーンが登録された

次にUnityメニューのFile→Build SettingsでScenes In BuildにLoaderシーンだけ追加します。

Scenes In BuildにLoaderシーンを追加する

これで機能が出来ました。

ダウンロードの状況を確認する際は実際にリモートのプロファイルをそのまま使ってサーバーにアセットバンドルファイルをアップロードして確認してもいいんですが、ローカル上で確認することも出来ます。

Addressables GroupsウインドウのPlay Mode ScriptをSimulate Groupsにすることでダウンロード状況をシミュレートすることが出来ます。

シーンの追加をせず常に1つのシーンにする場合

先ほどのサンプルではLoaderシーンに追加でシーンを読み込み、他のシーンが必要になったら前のシーンをアンロードして新しいシーンを読み込むという方法を行いました。

しかしLoaderシーンを使わない方法もあり、その場合は

とLoadSceneMode.Additiveとしていた部分をLoadSceneMode.Singleとすることでシーンを読み込んだら前のシーンを破棄する形に出来ます。

ただその部分だけを変えただけでは出来ないので、LoaderゲームオブジェクトとLoaderスクリプトを次のシーンへ引き継ぐ必要があります。

Unityでシーンを移動した時のデータやゲームオブジェクトの引き継ぎ
Unityのゲームで別のシーンに移動した時に前のシーンで使っていたゲームオブジェクトやデータを今のシーンで使う方法を考えていきます

LoadSceneMode.Singleでシーンをロードした場合は、前のシーンの参照カウントがゼロのアセットはアンロードされるようです。

LoadSceneMode.Singleで常に1つのシーンにする場合はUIのイベントを実行する為に各シーンにEventSystemが必要になります。

アセットの依存関係を解決する

複数のシーンでAddressablesに登録した同じアセットを参照している場合アセットバンドルが重複してしまいます。

試しにUnityのスタンダードアセットのThirdPersonControllerをAddressablesのMyGroupsに登録し、Title、Stage1、Stage2シーンがスタートした時にAddressablesに登録したThirdPersonControllerをインスタンス化して使用する場合を考えます。

まずはスタンダードアセットのThirdPersonControllerのインスペクタでAddressablesにチェックを入れMyGroupに登録します。

ThirdPersonControllerをAddressablesに登録する

Title、Stage1、Stage2シーンのそれぞれにスタンダードアセットのThirdPersonControllerをドラッグ&ドロップします。

ThirdPersonControllerはAddressablesに登録しましたが、各シーンで重複したキャラクターがいることになります。

重複したアセットがある場合に不具合が発生する可能性もあるので?これを解決します。

UnityメニューのWindowからAsset Management→Addressables→Analyzeを選択し、Addressables Analyzeウインドウを開きます。

Analyze Selected Rulesボタンを押します。

Addressables AnalyzeのAnalyze Selected Rulesボタンを押す

そうすると分析が実行され、Fixable Rules(修正可能なルール)の部分でバンドルの依存しているアセットが重複している物が複数あることがわかります。

そのままFix Selected Rulesボタンを押すとAddressables Groupsウインドウには依存が重複しているアセットがDuplicate Asset Isolationという新しいグループにまとめられるようになります。

これで依存しているアセットは別グループに分けられることになります。

重複した依存アセットが別グループに移動された

WebGL形式で実行する際の注意点

わたくしはWebGL形式でAddressablesの機能を使おうとしていたんですが、色々エラーが出たのでもしWebGL形式でAddressablesを使う際に注意をした方がいい点を書いておきます。

既に記事中に書いていますが、

  • グループのAsset Bundle CompressionでLZMAにすると解凍が出来ないのでLZ4を選択することで解消する場合がある
  • Addressables GroupsウインドウのPlay Mode ScriptをUse Existing Buildを選択してエディター上で実行すると音声ファイルのエラーで失敗する
  • その他Addressablesとは関係なくWebGL形式で出力してブラウザでエラーが出る場合は

    UnityメニューのEdit→Project SettingsのPlayerのPublishing SettingsでCompression FormatをGzipにし、Decompression Fallbackにチェックを入れなかった場合は.wazm、.gz等のファイル形式のContent-Typeを記述した.htaccessファイルをそれらのファイルと同じ階層に作成する必要があります。

    ここら辺はUnityマニュアルにサーバーソフトの種類に応じた設定方法が書いてあるので参考にしてください。

    WebGL: Server configuration code samples - Unity マニュアル
    The code samples below show how to configure your server when working with WebGL. The following samples apply to IIS and Apache servers. For further information...

    わたくしの場合はロリポップのハイスピードプランでLiteSpeedですが、Apacheの設定と同じようにしてもエラーが出ます。

    LiteSpeedの場合は

    UnityWebGL-LoadingTest/.htaccess at master · JohannesDeml/UnityWebGL-LoadingTest
    Testing loading speed and build size of WebGL builds for different Unity versions - UnityWebGL-LoadingTest/.htaccess at master · JohannesDeml/UnityWebGL-Loading...

    上の方が書いているような書き方で.htaccessファイルを作成する必要があります。

    その他、FS.syncfs operations系の警告がブラウザに表示される場合は以下のフォーラムに解決策が書いてあります。

    warning: FS.syncfs operations in flight at once, probably just doing extra work
    I'm getting an old game running on webGL for the first time ever, using Unity 5.5p1. So far I have everything working but the (chrome) console every 8...

    ただライブラリファイルの編集の仕方がわからないので、わたくしはダメでした。(^_^;)

    Use AssetBundle Cacheにチェックを入れた場合はアセットバンドルをロードした時にブラウザがクラッシュしたので、WebGL形式の場合はUnityメニューのPlayer SettingsのPlayerのPublishing SettingsのEnable Exceptionの設定をデフォルトのExplicitly Thrown Exceptions Onlyから他の設定(NoneやFull With Stacktrace)に変更して試すとクラッシュはしなくなりました。

    またWordPressでHTMLにscriptタグを埋め込んでWebGLファイルを読み込む時にscriptタグ内のスクリプトで空白の行を入れているとエラーになり、実行出来ない可能性もあるので、空白の行がある場合はその行を削除して実行してみるといいかもしれません。

    参考サイト

    UnityマニュアルーAddressablesー

    Unity Learn-Getting Started with Addressables-

    以下の動画シリーズは非常にわかりやすいです。

    https://www.youtube.com/watch?v=0USXRC9f4Iw

    終わりに

    Addressablesの理解を進めるにはとりあえず実行してみるしかありませんね。(^_^;)

    AddressablesのエラーなのかWebGLで出力したことによるものなのか、サーバーの種類によるエラーなのかわからないことも多いです。

    でも、とりあえず記事に出来たので、忘れた時には自分の記事をみて利用することにします。(^_^)v

    タイトルとURLをコピーしました