テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】PrefabにScriptableObjectを格納する

f:id:tsubaki_t1:20170803233437j:plain

今回はPrefabにScriptableObjectを格納する話です。

ScriptableObjectを使うと何が良いの?

Prefabをインスタンス化する場合、コンポーネントの複製が行われます。もしインスタンス化したPrefabのパラメータが殆ど変更無い場合は、これは非常に無駄になります。

例えばEnemyというPrefabを作成し、EnemyStateコンポーネントには以下のようなデータが大量にあったとします。

  • 敵の名前
  • パラメータ
  • スキル一覧
  • アニメーション一覧

そういった場合、オブジェクトをインスタンス化する度に、コンポーネントはこれらのパラメータを格納するメモリを要求します。また、パラメータの流し込みコスト(地味に重い)が発生します。
あと開放コストも地味に増えます。DestroyやUnloadが妙に重い場合は、単純に数が多すぎたり、パラメータが多すぎたりするのを直すと、治ったりします。

f:id:tsubaki_t1:20170803235036j:plain

コレを回避する最も手っ取り早い方法がScriptableObjectにパラメータを退避する事です。Prefabは一つのScriptableObjectを参照し、Prefabからインスタンス化したオブジェクトは一つのScriptableObjectを参照する。
これならばロードコストもパラメータのメモリ消費も1回で済みます。

f:id:tsubaki_t1:20170804000226j:plain

ただ、ScriptableObjectを生成するとプロジェクトが散らかります。1Prefab 1ScriptableObjectと考えても、Prefabが100体になると管理が煩雑になる事が予想されます。

f:id:tsubaki_t1:20170804000110j:plain

SriptableObjectをPrefabに格納してしまおう

指定Prefabしか使わないのに別にScriptableObjectを用意すると色々と管理が面倒そうなので、Prefab内にScriptableObjectを格納してしまいます。

こんな感じに。

f:id:tsubaki_t1:20170804000930j:plain

f:id:tsubaki_t1:20170804083402j:plain

サンプル

サンプルコードでは、PrefabのコンテキストメニューからAddを足すとScriptableObjectが追加され、Removeすると破棄されます。

このPrefabから生成したインスタンスは全てPrefabに格納したScriptableObjectを参照している感じです。

f:id:tsubaki_t1:20170804001523g:plain

gist.github.com

 

f:id:tsubaki_t1:20170804000433j:plain

Tips

  • Prefabかどうかの判定は、 PrefabUtility.GetPrefabTypeが楽です。
  • Prefab内のオブジェクトを取り出すのはAssetDatabase.LoadAllAssetsAtPathです。
  • Prefabの中に格納したScriptableObjectのOnEnableはPrefabを参照していると自動で呼ばれます。