sound sepher's PASTIME

ゲーム開発で思ったことや、趣味などの話を書き綴っていきます。

【Unity】AddressableAssetSystemメモ

前書き

まだよくわかってないので調べてみた内容をまとめておきます。
間違ってるところとかあるかも。

ScriptableObject 関連

AddressableAsset に組み込む際の要点

  • ScriptableObject にアセット(Prefabなど)の参照を入れて AddressableAsset をビルドすると、
    参照されているものも丸ごと bundle ファイルに入る
  • ScriptableObject の中で ScriptableObject を参照した場合、
    その ScriptableObject で参照されているアセットも bundle ファイルに入る
  • ただし、その親 ScriptableObject 下で参照したアセットが被っていると、
    さすがにアセットひとつのみのロードで済むっぽい

  • 本番環境 (Use Existing Build) とテスト環境 (Use AssetDatabase) で参照アセットが変わる

ScriptableObject に Prefab を配置すると bundle に含まれてしまう件

問題
  • ScriptableObject をロードすればその下の Prefab も一緒にロードできる
    …が、データベースを組むときに Prefab や Image まで含めてしまうと、
    AddressableAsset のデータを小分けにロードできるメリットが失われる。

    データベースなのにやたらサイズが大きくなるし、ロードが遅くなる。
解決方法
  • AddressableGroup で別途アセットを配置したグループを作る。
    これを AssetReference で参照すると Group(bundle)に含まずに済む。

    ただしアセットを別途ロードしないと実体化できない。ちょっとめんどい。

疑問点1(→解決済)

  • ScriptableObject の中で AssetReference を置いたとき、
    スクリプトから参照してインスタンスすると null でエラーする??

    • ロード処理(下記画像だと LoadWaitAsync)の while の条件式の問題だった。
      while は ”条件式が真であるとき” ループし続ける仕組みなので、
      PercentComplete < 1 だと 1 にならずに抜ける。<= だと永遠に回り続ける。

      ので、確実にハンドルに参照が入ったかどうかをチェックする
      handle.Result == null を使って、ロードが完全に終了したかどうかを見た。

f:id:Ashtarte:20200716195359p:plain

f:id:Ashtarte:20200716200538p:plain

疑問点2(→解決済)

  1. AddressableAsset の PlayModeScript の Use Existing Build を選択時
    ScriptableObject を直接グループに紐づけした状態で LoadAssetAsync した際、
    該当する ScriptableObject は Project にある同名の ScriptableObject とは別扱いになるっぽい。

  2. つまり Project にある同名のアセットの値を変更しても反映されないということ。
    ロードしたアセットは Project の同名アセットとは別扱いになる。

  3. Addressables経由 ScriptableObject 下にあるprivateメンバーの値が読めない。なぜ?
    数値を変えたい private メンバーは [SerializeField] 属性をつけること!(ポカミス)

  4. ちなみに AssetReference 経由の場合、オブジェクトの実体は editorAsset 経由で拾える。
    handle.Result.assetReferenceGameObjects[0] では null を吐き出す。
    正解は handle.Result.assetReferenceGameObjects[0].editorAsset
    ただし、editorAsset を使ってると アセットのビルド時にエラーを吐く。
上記の問題群に対する回答案
  • PlayModeScriptの Use Asset Database ではアセットビルドを参照しない
    このモードでは Project上 の ScriptableObject 等アセットを参照する(確認済み)ので、
    開発中は Use Asset Database で直接参照状態にしてデバッグ
    本番ではビルドして Use Existing Build で実行。

  • 直接参照状態なら、Addressables からロードした別インスタンスにはならない。
    エディタから ScriptableObject の値を変えてもランタイム終了時に保持される。
    • インスタンス状態になると、本番環境ではランタイム終了時に消える

AssetReferenceTypeRestriction は廃止された

下記が詳しい。

ジェネリック型は通常のインスペクターで確認できない。
Odin でも AssetReference には対応してないのでどうしようもない。

kurokuru.github.io

補足1

ちなみに下記のようなものが模様。いろいろあるなあ。
LoadAssetAsync<T>(文字列)文字列部分に下記の型の変数を配置すればOK。

  • AssetReferenceAtlasedSprite
  • AssetReferenceGameObject
  • AssetReferenceSprite
  • AssetReferenceT<>
  • AssetReferenceTexture
  • AssetReferenceTexture2D
  • AssetReferenceTexture3D
補足2

AssetReference は Odin の [PreviewField] で画像ウィンドウが出せない。つらい。