【Unity】PrefabにScriptableObjectを格納する
今回はPrefabにScriptableObjectを格納する話です。
ScriptableObjectを使うと何が良いの?
Prefabをインスタンス化する場合、コンポーネントの複製が行われます。もしインスタンス化したPrefabのパラメータが殆ど変更無い場合は、これは非常に無駄になります。
例えばEnemyというPrefabを作成し、EnemyStateコンポーネントには以下のようなデータが大量にあったとします。
- 敵の名前
- パラメータ
- スキル一覧
- アニメーション一覧
そういった場合、オブジェクトをインスタンス化する度に、コンポーネントはこれらのパラメータを格納するメモリを要求します。また、パラメータの流し込みコスト(地味に重い)が発生します。
あと開放コストも地味に増えます。DestroyやUnloadが妙に重い場合は、単純に数が多すぎたり、パラメータが多すぎたりするのを直すと、治ったりします。
コレを回避する最も手っ取り早い方法がScriptableObjectにパラメータを退避する事です。Prefabは一つのScriptableObjectを参照し、Prefabからインスタンス化したオブジェクトは一つのScriptableObjectを参照する。
これならばロードコストもパラメータのメモリ消費も1回で済みます。
ただ、ScriptableObjectを生成するとプロジェクトが散らかります。1Prefab 1ScriptableObjectと考えても、Prefabが100体になると管理が煩雑になる事が予想されます。
SriptableObjectをPrefabに格納してしまおう
指定Prefabしか使わないのに別にScriptableObjectを用意すると色々と管理が面倒そうなので、Prefab内にScriptableObjectを格納してしまいます。
こんな感じに。
サンプル
サンプルコードでは、PrefabのコンテキストメニューからAddを足すとScriptableObjectが追加され、Removeすると破棄されます。
このPrefabから生成したインスタンスは全てPrefabに格納したScriptableObjectを参照している感じです。
Tips
- Prefabかどうかの判定は、 PrefabUtility.GetPrefabTypeが楽です。
- Prefab内のオブジェクトを取り出すのはAssetDatabase.LoadAllAssetsAtPathです。
- Prefabの中に格納したScriptableObjectのOnEnableはPrefabを参照していると自動で呼ばれます。