【Unity】IExposedPropertyTableを使った、アセット↔シーン間連携
今回はPlayableDirectorで使用しているIExposedPropertyTableを利用してみます。
正直言えば使える機能では無いように思いますが、この実装からTimelineのResolver運用周りを見直すことが出来たら幸いです。
IExposedPropertyTableはアセットからシーン内のオブジェクトを参照する
IExposedPropertyTableは、PlayableDirector(Timeline等)で使用されているアセットからシーン内のオブジェクトを参照する為のインターフェースです。
厳密には異なるかもしれませんが、用途としてはそんな感じです。
基本的にUnityはシーン間参照が出来ません。シーン内のオブジェクトがシーン内のオブジェクトもしくはシーン外のオブジェクトを参照する事は可能なのですが、シーン外のオブジェクトからシーン内のオブジェクトへアクセスする場合には、動的にオブジェクトを参照する必要があります。
IExposedPropertyTableは、上でも紹介している通りアセットからシーン内部のオブジェクトを参照する際に使用できます。
TimelineのPlayableAsset(Timelineを定義したもの)がシーン内のオブジェクトを参照するために、こういった機構が必要になったという感じです。
まぁ、コードを見れば分かるのですが最終的にScriptableObjectを動かしてるのはSceneのコンポーネントなので、もっと良い手が一杯あるんじゃないかなという気もしますが。
IExposedPropertyTableを実際に使用してみる
実際に使用してみます。
やることとしては、「動作とパラメータを持つScriptableObject」と「シーン内のオブジェクトを選択するIExposedPropertyTableを持つコンポーネント」を用意し、ScriptableObjectにコンポーネントの動きを制御してもらいます。
今回の内容では、ScriptableObjectに指定したオブジェクトとカメラを回してもらいます。こんな感じ。
サンプルコード
まずはサンプルコードをプロジェクトに入れてみます。
ResolverTestがコンポーネントの割当を行う処理、SampleDataがシーン内のオブジェクトを操作するScriptableObjectです。
SampleDataのDoの内容を書き換えると、他の操作を実現できます。
ScriptableObjectのセットアップ
ScriptableObjectのセットアップです。
単純に、ScriptableObjectを作るだけですが。
シーン内のオブジェクトとScriptableObjectをバインド
次にシーン内のオブジェクトとScriptableObjectをバインドします。この手順はややっこしいです。
- 適当なオブジェクトにResolverTest コンポーネントを登録します。
- (初回のみ)ObjとMainCameraの項目を、Expose Propertyします。
- オブジェクトをドラッグ&ドロップで登録します。
要素を増やす
要素を増やしたい場合、サンプルコードならSampleDataのExposedReferenceを増やせばOKです。
コンポーネント側は特に変更なく、Sceneの操作とScriptableObjectの定義の変更で行けます。
Expose Propertyって何してるの?
ScriptableObjectにExpose Nameをセットしています。
Resolver TestはこのExposedNameを保持しているので、ScriptableObjectは同一のExposedNameを参照出来ている感じです。
これを行わない場合、Default Valueを使用するみたいですが、その後のフローが意味不明なので触らない方が吉です。
なお、Expose NameはどうもGUIDを生成しているらしく、要するに一度Unexpose Propertyすると他の参照関係が全て駄目になります。
さらに言えば、参照するためのIDが毎回個別に発行される為、SampleDataを継承して多様性的な使い方をしようと思った時、参照先のオブジェクトを全て再登録する必要が出てきます。「クラス名と要素名のパスからのハッシュ」で作ってくれたら楽なんですが…
異なる振る舞いを流し込む的な
クラス名やら要素名やらでハッシュを作ってくれない問題ですが、実は自分でExposedNameをセットしてやれば良いです。
それをもう少し発展させて「振る舞いが異なるが引数が同一の動作の流し込み」を行ってみます。
ソースコードはこんな感じ。
特徴はSampleDataが抽象クラスに変更している点と、SampleDataを継承しているクラスの存在です。
SampleDataを継承したSampleAction達には、異なる動作が定義されており、かつ引数も異なる引数を定義できます。共通の項目は同一のパラメータを使います。
一つの定義で複数の異なるオブジェクトを動かす
IExposedPropertyTableのstatic系との違いは、複数のインスタンス存在出来る点かなと思います。
staticだと登録できるオブジェクトは全体で一つ、これを複数にすると色々と面倒になってきます。
IExposedPropertyTableを使用した場合は、複数のオブジェクトにScriptableObjectで定義した動作を流し込める点が便利です。
まぁ…これが使えるのはSO内にキャッシュを持ってない場合のみで、キャッシュを持つと使えなくなる、しかしキャッシュしないとパフォーマンスのジレンマがありますが。
関連
動画の解説
ソースが動画でしか紹介されておらず、かつ全文を公開していないので、実際に試すのに無駄な時間がかかります。
良いお年を。