DynamicVariableを始めてみる

DynamicVariableはとても便利です。
最近、NeosVRでなにか作るときは大抵DynamicVariableSpaceをつけるところから始まります。


今回の記事のターゲットはNeosVRで何か色々作ってるけど、DynamicVariable知らない・分からない…人向けです。

・はじめかた
・各機能
・使用例
・つまづきポイント

##触ってみる
コンポーネントをつけていきます。

①DynamicVariableSpaceをつけます。
Data/Dynamic/DynamicVariableSpace
DynamicVariableはこのコンポーネントがついたSlot以下の階層で使用できます。
SpaceNameは入力しなくても機能します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/1dcd6428-2dfb-9d7c-43d9-84456d9d813a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/b48e91bb-cd9c-f490-5eb3-cf9f8a19ced9.png)


②DynamicValueVariable<T>をつける。
Data/Dynamic/DynamicValueVariable<T>
型を選ぶ必要があります。
stringを入れてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/b7bc47cf-b5a0-f19e-0674-eaa2f29fb9ce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/fc4ccadb-9350-5815-c42f-a7727a537249.png)

③値を入力しておきます。
VariableNameはUserName
Valueにrheniumを入れてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/ca12bf34-73e2-5229-0471-cb7a3441624b.png)

④LogiXから値を取ってみます。
ノードを出します。
Variables/DynamicValueInput
を選択します。型を選ぶ必要があるので、stringにしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/1cb81b72-fd0d-77b9-649e-54145eb57e2c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/4a6adbea-5e5a-50cf-691d-e4c1fa15008c.png)

不思議なノードが出てきました。
VariableNameを入れましょう。
さきほど入力した「UserName」を入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/4d6bf8a2-87b9-a815-856e-36464f8a9219.png)
出してすぐのノードはRootにあります。
DynamicValueInputノードは同じDynamicVariableSpaceから値を取得するため、うまく動かすためには一度Packingする必要があります。
（Packingするとノードは対象のSlot以下に配置されます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/4aae9d39-77b5-ee93-8fff-23bb0eb5559b.png)

Unpackすると値が取れている様子を確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/81df7475-2d71-b1f8-0ad4-91cac2800370.png)


##各機能

###Component
ComponentはValueとReferenceがあります。
やっていることは同じですが、Valueはintやstringなどの値そのものの型を、ReferenceはUserやSlotなどの参照となっている型を対象にしています。

####DynamicField/DynamicReference
指定したFieldをDynamicVariableにすることができます。
ComponentのFieldにつけていくと擬似的にLogiXからComponentの値を変更できるようになるため便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/7565328a-6c24-7934-7a5e-5a1eaf6c2388.png)

####DynamicValueVariable/DynamicReferenceVariable
先の例でも使ったField自体まで持っているComponentです。
よく使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/8d104c4e-3078-8cfd-457d-46593e29799e.png)

####DynamicValueVariableDriver/DynamicReferenceVariableDriver
指定したFieldを指定したVariableNameの値でDriveします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/909de2f9-d4e3-1860-efc8-0fdd19b9af6a.png)

####DynamicValeVariableReset/DynamicReferenceReset
特定のタイミングでDynamicVariableの値を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/c58cdc74-3b1d-4594-a6c0-e170ec118cb3.png)


###LogiX
####DynamicVariableInput
先の例でも使ったものです。指定した名前のDynamicVariableの値をこのノードが存在するDynamicVariableSpaceから取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/21d7b796-20be-4618-f657-fb740f05f5a8.png)

####ReadDynamicVariable
指定したSlotの属するDynamicVariableSpaceから指定した名前のDynamicVariableの値を取得します。
※値が自動更新されません。できるだけDynamicVariableInputを使うことが推奨されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/dd2569d1-f96d-a7fc-af0d-5f886829e654.png)

####WriteDynamicVariable
指定したSlotの属するDynamicVariableSpaceの指定した名前のDynamicVariableの値を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/cbf5cd9d-1fec-8682-f4f8-30c3010d8606.png)

####WriteOrCreateDynamicVariable
指定したSlotの属するDynamicVariableSpaceの指定した名前のDynamicVariableの値を書き換えます。存在しなければ、新しく作ります。
２つのBoolのオプションがあります。
1.CreateDirectOnTarget
デフォルトはFalse。Falseの場合は対象のDynamicVariableSpaceと同じSlotにComponentを付与しますが、これをTrueにしていると指定したSlotに直接つけることができます。
2.CreteNonPersistent
デフォルトはFalse。これをTrueにするとワールドやインベントリへの保存時に保存されません。
一時的なデータを作るときに便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/b91ccae8-bd39-2776-adf2-8c8249e71ec1.png)

##使用例
一例ですが、私がよく使う使いかたを書きます。

###単に名前をつけるために使う
LogiX上でどこに繋がっているか分からないRefや何を表しているか分からないマジックナンバーを排除するために使います。
一番分かりやすい使いかただと思います。慣れるためにもおすすめです。
複数人で作業するときもわかりやすくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/d501e997-f884-57e4-6757-1bc50c6fd38e.png)

###DynamicImpulseTriggerWithValueで複数のパラメータを送りたいときに使う
DynamicImpulseTriggerWithValeは便利なノードですが、複数の値を送れないのが難点でした。
送信用のDynamicVariableSpaceを用意しておき、TriggerではそのSlotを送信し、受信側はReadDynamicVariableを使用して値を取ることで、比較的分かりやすく複数の値を送ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/ebf384c3-3789-82a8-25b2-1a3242f98418.png)

###カラーテーマ
予めどこに使う色か名前を決めておき、DynamicValueVariableDriver<Color>でDriveして作ったUIです。
色を変えると対応する箇所が全て変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547843/c277f233-a3a1-290e-ddbf-47f5727385c2.png)


###ロジックとUIの分離に使う
LogiXでは、DynamicVariableの値のみを操作し、DynamicVariableの状態に応じてUIを書き換えるように作るとロジック部分とUI部分を分けやすいです。
こうして作っておくと後々アイテムの見た目のみを大幅に変えたいときもスムーズに変更できます。

###辞書として使用する
WriteOrCreateDynamicVariableノードを使用して動的にDynamicVariableを増やすことができます。
キーとそれに対応する値を取得できます。

外部サーバーからWikiデータを取得する際、毎回アクセスするのは無駄なので、Urlと対応したデータをキャッシュするのに使ったことがあります。


##はまりポイント
###VariableNameに一部の区切り文字は使えません。
「/」「-」などが使えません。（あといくつかあったけど思い出せない…。Frooxiusさんのアップデート情報にあったと思うので後日見つけたら追記します。）
「.」は使えます。

将来の機能追加のため予約されているそうです。

###DynamicVariableSpaceごとDuplicateすると2フレームのDelayをあけないと使えません。
DynamicVariableSpaceのついたSlotをDuplicateした場合、2フレーム待たないとDynamicVariableが機能しません。
UpdatesDelayWithValue<Slot>を使って待ってあげましょう。