ECS 0.0.12 preview 26
から、GameObjectとComponentをEntity&ComponentDataに変換する機能が追加されました。まずは、この中で最も便利であろうSubSceneについて紹介します。
GameObjectをECS向けに変換する
preview26でGameObjectConversionUtility.ConvertGameObjectHierarchy(...)
やGameObjectConversionUtility.ConvertScene(...)
等のAPIが追加されました。このAPIは特定のコンポーネントを対応するComponentDataに変換するといった機能を持ています。例えば下のような感じ。
- Transformを
Position
とRotation
に変換する - MeshRendererとMeshFilterを
RenderMesh
に変換する
これはPrefabからEntityや、シーンに配置したGameObjectからEntity、SceneまるごとEntityといったレベルでの変換が可能です。
当然、変換なので変換先のComponentDataが無い物は変換出来ない為に完全簡単に移行という訳には行きませんし、現状、ライトマップ等のSceneに紐づく情報は剥がれます。が、Unityエディターのワークフローでシーンにオブジェクトを配置し、ゲームで利用する事が可能になるのでECSを利用する上では、使いやすくなりそうです。
ということで実際にScene上のステージをEntity群に変換して利用して見るわけですが、そこで既に便利な機能「SubScene」があったので、そちらを使います。
SubScene
SubSceneの説明によると、機能は大体こんな感じみたいです。Unityがシーン展開に使用しているようなデシリアライズとは異なり、ECSのメモリ構造を概ねそのまま展開して配置出来るので楽という発想でしょう。
シーンを保存する時、UnityはSubSceneをネイティブのバイナリフォーマットに変換します。このフォーマットはメモリに対応していて、RAM内のデータを少し変更するだけでロードもしくはストリーミングが可能です。このフォーマットは大量のEntityをストリーミングするのに理想的です。
いくつかのロードが超早いと評判のゲームは、このアプローチを使っていると聞いていたと聞いているので、とても良さそうです。
実際に使ってみる
【動作環境】
1. 選択したオブジェクトのサブシーン化
シーンにあるオブジェクトをサブシーンにします。
オブジェクトを選択して 右クリック→New SubScene from Selection
をクリックすると、指定した範囲内のオブジェクトをサブシーンにします。Stageのようなオブジェクトが既に存在し、Colliderとは別に配置されている場合には、こちらのほうがやりやすいかもしれません。
よくあるGameObjectをサブフォルダのように使うが如く、シーンを階層化出来ます。SubSceneの下にSubSceneを配置するなども可能です。
シーンファイルは、親シーンと同名のフォルダ以下に配置されるみたいです。
なお、基本的に動かさないオブジェクトにはStatic Optimize Entity
を追加します。これを追加してあると、描画時に軽くなります(staticフラグが付いてるなら自動で設定してくれても良いのに)
2. SubSceneの編集
SubSceneに持っていっても、編集は可能です。
Edit
ボタンを押せば、Entity & ComponentDataの代わりにGameObject & Componentが表示され、編集することが出来ます。この状態になると、普通のシーンと同様の操作系になります。
3. SubSceneをEntity群に変換
Entity群に変換します。
変換するには、SubSceneのRebuild Entity Cache
ボタンを押すだけです。
既存のシーンの場合は、SceneAssetに追加すれば変換が可能です。
この手順が完了すると、Assets/EntityCache/Resources
フォルダとStreaming Assets/EntityCache
フォルダにEntityをシリアライズしたファイルが生成されます。
PrefabはSharedComponentDataをシリアライズした情報、あとはSceneHeader(シーン情報とシリアライズしたバイナリを紐付ける)といった感じでしょうか。
また変換後でもEditボタンで編集が可能です。
これでゲームを実行すると、Sceneから変換したEntity群がロードされます。
SubSceneに変換出来ない場合
変換出来ない場合、同一のコンポーネントが複数セットされている事が考えられます。
というのも、ECSは仕組み上「一つのEntityに同じComponentを複数登録できない」という制限があります。なので、Colliderなど一つのオブジェクトに複数のコンポーネントを登録しているものを排除します。
また変換出来ないEntityの情報は尽く剥がされます。これはスクリプトで拡張が出来ますが(Renderer等もHybrid Rendererパッケージで拡張されて変換可能になっている)無いものは変換出来ません。
ArgumentException: It is not allowed to have two components of the same type on the same entity. (BoxCollider and BoxCollider)
と出ます。
既存のシーンを変換する
上でもチラっと書きましたが、New SubScene from Selection
を使用してSceneを作らない場合でも、SubSceneのSceneAssetにSceneを適応すればSubSceneとして扱えます(変換も可能です)
ただし、その場合は一旦シーンを開き直さないとSubSceneをSceneと認識しませんでした。
その他機能
また、キャラクターのコンポーネント情報がどうなっているのか等を確認したい場合、LivelinkでEntityの情報をGameObjectに反映させるという事ができそうな感じがあります。
MeshRendererやLODは使えないの?
MeshRendererやLOD以外でも、独自スクリプトでも差し替えは可能そうです。詳しくはこちら
感想
まだ機能が限られていますが、現状でも「ステージの大雑把な情報やキャラクターはGameObject & Component」「細かく大量にあるステージ上の小物はEntityで制御」のような使い分けができそうです。
またSubSceneで一つのシーンを複数で分割し、同時編集するといった事も今までのマルチシーン構想よりスムーズにできそうです。特にGameObjectをフォルダのように利用して階層分けしていた場合、より高速でスムーズなアプローチとして期待出来るかもしれません。
ところでSubSceneは普通に現行のGameObjectベースのシーンシステムに欲しいんですが…
関連
データをロードする部分は大体コレ
SubSceneのサンプル
https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/Samples/Assets/HelloECS/HelloCube_04_SubScenegithub.com