[neos(NeosVR)]Dynamic Impulse Trigger(Receiver)の使い方

この記事では、neos(NeosVR)のDynamic Impulse Trigger(Receiver)の使い方について解説します。
簡単なサンプルも用意しましたので、実際に手を動かしながら学習してみると良いでしょう。

## 基本的な考え方
簡単に書いてしまうと、DynamicImpulseTriggerで呼び出してDynamic Impulse Receiverを実行するという関係のコードです。
全く階層の違うコードを呼び出して実行したり、共通の処理を1か所にまとめるなどしてLogiX実装の効率化が可能な機能です。
最初のうちはプログラミングでいうところの関数と同じ感覚で考えるのが良いと思います。

## 具体的な使い方
サンプルを用意したので、これを使って解説します。

下記リンクをコピーして、neos内で貼り付けをしてください。
現れた共有フォルダを保存してダブルクリックするとアクセスできます。
```
neosrec:///U-e1ght3/R-a3337209-dd78-4f84-8f25-5f5ca30f98d3
```


![20220411200240_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/964236a9-0fc2-dd3b-4ec2-007a1d66750e.jpeg)
サンプルは
テキストフィールドに好きな文字列を入れたボタンAかボタンBを押すと、右側のテキストがその文字列に入れ替わるというシンプルなものです。


![20220411200326_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/42e15c94-7527-5245-1bda-06ac83b498c5.jpeg)
ButtonAもButtonBも中身は同じ構成・コードで作られています。
Dynamic Impulse Trigger With Value`1を実行している側です。

Resultは逆に値を受け取ってテキストを書き換えるコードが入っています。
Dynamic Impulse Receiver With Value`1を実行している側です。

### サンプルコード解説
#### Dynamic Impulse Trigger
![20220411195028_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/7bf2a863-ca2e-1149-2518-8768fc89df6b.jpeg)

コードは極めてシンプルで、ボタンを押したらすぐにDynamic Impulse Trigger With Value`1を呼び出しているだけです。
上から順に、
1つ目は、パルスなので割愛。
2つ目は、いわゆる関数名にあたるものを指定します。ここではわかりやすく「SetText」としました。

3つ目の黄緑色は、「Result」のSlotを指定しています。
恐らくDynamic Impulse Triggerがわからない方はここの指定の仕方で悩んでいる方が多いのだと思います。
Dynamic Impulse Triggerが実行される際、
```
指定したSlotより下の層のSlotを検索して、
指定したDynamic Impulse Receiver(今回の場合は「SetText」)を探す
```
という動作をします。
![Inked202204112100326_1_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/8d18f1e5-d966-87eb-ffb7-726b2da5ef3c.jpeg)
なので、今回のコードに関して言えば指定するSlotが仮に「sample」でも「Result/LogiX」でも問題なく動いてしまいます。
それは指定したSlotよりも下の層でかつ「SetText」が指定されたDynamic Impulse Receiverが一つしかないからです。
「ButtonA」や「ButtonB」を指定した場合は動作しません。これらのSlotの下には「SetText」が指定されたDynamic Impulse Receiverは存在しないからです。

ただし公式wikiにも記載がある通り、処理自体は高速ではあるものの検索処理はそれなりに負荷がかかっていると思われる為、出来るだけ目的のコードがあるSlotに近い層のSlotを指定することが重要となります。
特にリアルタイム処理が必要となるゲームなどを作る場合、Dynamic Impulse Triggerは出来る限り多用を避けることがゲームを高速動作させるコツとなります。

4つ目はテキストフィールドの入力された値をそのまま引っ張ってきて渡す値(≒引数)としています。


#### Dynamic Impulse Receiver
![20220411195226_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/481162cc-b984-acac-16bc-564f29ed054a.jpeg)

こちらも極めてシンプルなコードです。
Dynamic Impulse Receiver With Value\`1で受け取ったstringをそのままOutlineのテキストに書き込んでいるだけです。
注意すべき点としては、Dynamic Impulse Trigger With Value\`1で実行した場合その受け側は必ずDynamic Impulse Receiver With Value`1でないと正常に動作しません。
Dynamic Impulse Triggerの場合はImpulse Receiverである必要があります。

## 応用例
今回のサンプルでは、「同じ処理をDynamic Impulse Receiverで一纏めにする」でしたが
例えば同じ構造のSlot群を並べてFor文やWhile文を使うことで、
「同じ構造を持つSlot群に対して同じ命令を一気に実行する」ことも可能です。
拙作のProtoPsychoでは、ステージ内の動的オブジェクトを一律同じ構造にしてfor文と組み合わせることで、初期化やリセット処理を常に1コードで実行できるように工夫しました。
https://twitter.com/e1ght3/status/1497812944486551558?s=20&t=XBTLEvSEIECurPooeha-hA
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">VR操作専用の超能力ACTゲーム「ProtoPsycho」を公開しました。<br><br>サイコキネシスを駆使して、与えられた課題をクリアしよう。<br>MMC22に応募しています。投票よろしくお願いします。<a href="https://t.co/ZNpqVsYpby">https://t.co/ZNpqVsYpby</a><a href="https://twitter.com/hashtag/mmc22?src=hash&amp;ref_src=twsrc%5Etfw">#mmc22</a> <a href="https://twitter.com/hashtag/NeosVR?src=hash&amp;ref_src=twsrc%5Etfw">#NeosVR</a><br><br>↓以下、注意事項 <a href="https://t.co/r5yC5jxu27">pic.twitter.com/r5yC5jxu27</a></p>&mdash; e1ght3 (@e1ght3) <a href="https://twitter.com/e1ght3/status/1497812944486551558?ref_src=twsrc%5Etfw">February 27, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

また、今回は1つの値(string)のみを使いましたが
複数の値を使用する場合は、
[1]空のSlotを作成する
[2]そのSlotの中にDynamic Variableを必要なだけ追加する。(必要に応じてDynamicVariableSpaceも)
[3]Impulse Trigger With Value`1(Slot)ノードを追加
[4]Slot指定箇所(サンプルでいうとStringだった箇所)に[1]で追加したSlot指定する
[5]引数のSlotを使ったRead Dynamic Variableで目的の値を取り出す。
で可能です。
ここでは詳細な解説は割愛します。


## 最後に
簡単ではありますが、「Dynamic Impulse Trigger」と「Dynamic Impulse Receiver」の使い方の解説は以上になります。
最初にも書いた通り、最初のうちは大まかな扱い方は関数と同じものと考えていただいて問題ありません。
ただし、通常のプログラムとは違い
●返り値の概念は用意されていない(自力でどこかしらに書き込んでおく必要あり)、
●同じSlot内のDynamic Impulse Receiverを何度も呼び出して再帰は出来ない(工夫すれば疑似的には可能)
など細かい使い勝手は違う為、実際に使いながら慣れていく必要があると思います。

## (オマケ)DynamicImpulseTrigger(Receiver)の詳細情報

DynamicImpulseTrigger
https://wiki.neos.com/Dynamic_Impulse_Trigger_(LogiX_node)/ja
![スクリーンショット 2022-04-06 182518.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/24ae5ef7-3078-a934-5051-f8e4ab9a9595.png)

Dynamic Impulse Trigger With Value`1(上記の値を渡せるバージョン)
https://wiki.neos.com/Dynamic_Impulse_Trigger_With_Value%601_(LogiX_node)/ja
![スクリーンショット 2022-04-06 190052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/65cf75a1-174f-64b0-0cc4-3611e56e0e39.png)

| 名前 | 色 | 説明 |
|:-:|:-:|:-:|
|パルス|白|通常のパルスと同じの為、省略。|
|Tag|赤|Tagの部分には任意の文字列を入れます。関数でいうところの関数名です。Slotに指定できるタグとは一切無関係です。|
|Slot|黄緑|Tagの名前で検索行う階層を指定します。指定したSlotより下の階層でかつTagで指定した名前と同じDynamic Impulse Receiverを探して実行します|
|Slot|黒|対象のDynamic Impulse Receiverを持つSlotがアクティブでないときに実行しないようにするか。デフォルトがFalseで、非アクティブでも実行します。|
|値|値の種類による|(Dynamic Impulse Trigger With Value`1のみ)関数でいうところの引数。intやFloat、Slotなどを指定できる。|

Dynamic Impulse Receiver
https://wiki.neos.com/Dynamic_Impulse_Receiver_(LogiX_node)/ja
![スクリーンショット 2022-04-06 190118.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/66ec5d6a-fb6e-3755-3dea-2f66db375a38.png)


Dynamic Impulse Receiver With Value`1
https://wiki.neos.com/Dynamic_Impulse_Receiver_With_Value%601_(LogiX_node)/ja
![スクリーンショット 2022-04-06 190147.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/b858f99d-0e8f-5f6b-672a-ec497ca9843e.png)