Addressable Asset Systemで、とりあえず Fast / Virtual Mode
ではちゃんと動くのに Packed Play Mode
では上手く動かないという場合の、経験則的な対策についてです。
- Packed Play Mode と Virtual mode / Fast Modeの違い
- ゲームの再生が出来ない
- コンテンツや設定の更新が反映されない
- UnknownResourceProviderException や Unable to read header from archive file:が出る
- Exception thrown in DynamicInvokeが出る
- Exception: RemoteAssetBundleProvider
- 404が出る
- 複数のPrefabでScriptableObjectを共有してるとき、ScriptableObjectの変更しても反映されない
- 複数のSceneでScriptableObjectを共有してるとき、ScriptableObjectを変更しても反映されない
- 感想
- 関連
Packed Play Mode と Virtual mode / Fast Modeの違い
Packed Play Mode と Virtual Mode や Fast Mode、この2つは非常に大きく異なります。
用途としてVirtualとFastはコンテンツの開発にフォーカスされており、動作の確認と修正を速やかに繰り返しやすい設計になっています。 VirtualはFastの高速性に加えて、コンテンツのロード・アンロードの動きを追跡しやすい設定です。アセットやAssetBundle開放のタイミングを把握することでメモリ管理に役立てようという発想です。FastやVirtualはAssetDatabaseから直接取得するタイプのロードを採用しており、AssetBundleをビルドし展開して使用する Packed とはロード方式が異なります。
一方、Packedは実際の動作と完全に同じ動きを行うことが期待されており、エディターでと言うよりは、実機での動作を確認することを期待するものです。実機で発生した不具合をエディターでも確認出来たら良いな程度に考えるのが良さそうです。
この2つ、ロード方式の違いから、Fast/VirtaulをPackedに上げると予想外の動きを起こす事があります。正確には 正しくない設定でも何となく動いてしまっていたものが、設定をちゃんとしないと動かなくなる なのですが、サクッと試すと結構混乱するので色々とメモします。
まぁ、Addressableさんのエラーメッセージが不親切の上に追いにくいというのもあるんですが…
ゲームの再生が出来ない
Packedに変更すると、ゲームの再生が出来なくなります。これはコンテンツ(AssetBundle)を作成していないためです。下のエラーメッセージを解決してやればビルドが可能になります。
Player content must be built before entering play mode with packed data. This can be done from the Addressable Assets window in the Build->Build Player Content menu command.
要するにBuild > Build Player Contentを押せば良いです。
これはBuild for content updateでコンテンツの更新を生成した場合も同様になります。
コンテンツや設定の更新が反映されない
コンテンツや設定の更新が反映されるのは、Build Player Contentでビルドした後からです。これは Addressable Asset Settings等での設定も含まれます つまり、RemoteLoad等の参照先を切り替えた場合、Build Player Contentの更新が必要です。
Catalog等の設定については案外StreamingAssets/aa/settings.json
を書き換えれば良いかもしれませんが、グループやプロバイダーについては再ビルドが必要です。
まぁ再ビルドといってもキャッシュが結構効くので、ファイル数が膨大でなければ(それこそ1Asset1AssetBundleとかしてなければ)割とサクっと終わる印象です。
UnknownResourceProviderException や Unable to read header from archive file:が出る
これはBuild Asset Group Schemaのプロバイダーの設定が間違っています。
このプロバイダーの設定は、現状1択で、異なる値を設定するとエラーが出ます。将来的にAddressableがAssetBundle以外のバイナリフォーマットに対応すれば話は代わりますが、現状のBuild ScriptはPack Mode1択なので、この2つが変化することはありません。
Unable to read header from archive file:
が出た場合はBundled Asset Provider Type(AssetBundleをどうやってロードするか)が間違っています。Bundled Asset Providerを設定します。
UnknownResourceProviderException
が出た場合はAssetBundle Provider Type(どうやってAssetBundleの中身を取得するか)が間違っています。Asset Bundle Providerを設定します。
なお変更が反映されるのは上に書いたとおり、Content Build Playerでビルドした後です。
Exception thrown in DynamicInvokeが出る
RemoteLoadPathを使用している状態で、ホスティングサービスやURL等を特に指定してない時に起こります。
Exception thrown in DynamicInvoke: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UriFormatException: Invalid URI: Invalid port specified.
ホスティングサービスを設定するなり、任意のサーバー上にファイルを設定すれば使えるようになります。
Schemaで確認したとき、RemoteLoadPathのアドレスがちゃんとなっていればOKです。
Exception: RemoteAssetBundleProvider
RemoteLoadPathを使用している状態で、ホスティングサービスが動作していない、もしくはアクセス出来ない(アドレスが間違ってる等)の状態です。
特にホスティングサービスを使用した時、初期設定はRemoteLoadPathの設定が明確に間違っているので、ちゃんと設定してやる必要があります。例えば http://[PrivateIpAddress_3]:[HostingServicePort]
等。 少なくともLoadPathには[BuildTarget]は使用しません。
404が出る
Hosting Serviceがちゃんと起動してないです。ホスティングサービスをUnityエディター起動後に初めて起動した時に出ます。
ホスティングサービスを再起動します。ポートが塞がってる訳でもないんですが、何ででしょう
複数のPrefabでScriptableObjectを共有してるとき、ScriptableObjectの変更しても反映されない
ScriptableObject等で値を共有している場合、共有用のScriptableObjectをAddressableに登録しないと、オブジェクトがPrefab毎に複製されて値が共有出来ないという事があります。例えばアドベンチャーサンプルゲームではシーン間の設定をSOで管理しているので起こります。
SO経由のデータ共有(いっそSO自体をマネージャーにする)はSingletonを使わず全体で動作にアクセス出来て楽で良いのですが、こういった事もあります。
これはScriptableObjectにアドレスを割り振り、複数のAssetBundleで共通のインスタンスを使わせれば良いです。Analyzeでも検出されました。
またResourcesとAddressableでScriptableObjectの共有は出来ません(どちらかがインスタンスの参照ではなく明示的な設定が必要になります)
複数のSceneでScriptableObjectを共有してるとき、ScriptableObjectを変更しても反映されない
上の設定に追加で、Sceneで使用する場合に注意が必要なのが、ゲーム開始時に開いているSceneが参照するリソースはAssetDatabaseから取得しているという点です。
これは基本的にAddressableに登録しているシーンは一旦Addressableシーンから起動してもらう事で回避が可能です。Packedは動作確認用なので、最初から確認してくださいということで。
感想
URLなど最初から明確に間違ってるのがありますが、ちゃんと設定すれば割とちゃんと動きます。逆に、ちゃんと設定してない箇所があると、ちゃんと動いてくれないです。
今回は基本的にPlaymodeがFastやVirtual Modeのときにちゃんと動くことが前提です。動かない場合は、多分アドレスが間違っているとかです。
関連
www.slideshare.net
後半に出てきたScriptableObjectによるデータ共有。テストとかやりやすい