NeosVR で初めてのオモチャ作成

購入したものの長らく眠っていた Oculus Quest を使って、先週から Neos VR という VRSNS に入り浸っています。

Neos ではゲーム内でノードプログラミングができる(LogiX という名前らしい)、という話を聞いてたので、試行錯誤しながらオモチャを作っています。この記事はそんな記録です。

ちなみにわかりやすい説明はいろいろと動画で出てるので、[Neos VR LogiX] とかで適当にググってください。この辺を参考に遊んでます。
youtu.be
youtu.be
youtu.be

ただ、残念なことに Neos の情報はネットに少なめです。どうしても詰まったら Neos にいる人に相談してみるといいかもしれません。今回の記事のオモチャも何度かテクを教えてもらってます。

今回作ったもの


時間経過で Rotation と Scale と色相が変わる箱です。(Position も変えたかったんですが、どう動かすのがいいか思いつかなかったのでやれてないです)

LogiX はこんな感じ f:id:trpg_yoshi:20210528193523j:plain

下記で少し細かく説明しますが、「たぶん」「おそらく」「と思います」などのふわっとした語彙がたくさん出てきます。なぜかというと Neos VR 始めて1週間程度のペーペーなので、詳しい理屈をまだ把握できてないからです。ご了承ください(予防線)。

準備

今回は箱を回すので、回す箱を作っておきます。ただ、箱の Rotation や Scale を操作すると Grabbable が反応しなくなるため、箱の親を作ってそれに Grabbable を付けておきます。
DevToolTip でコンテキストメニュー>新規作成>3D モデル>ボックスで箱を作ります。セカンダリーを当てた後にコンテキストメニューからインスペクターを開きます。Box の Grabbable コンポーネントを探して赤いXを押して消します。
Boxのスロットが開いてるところで、黄色い上矢印を押して親スロットを作ります。Box - Parent を選択して Attach Component>Transform>Interaction>Grabbable で Grabbable コンポーネントを追加しておきます。
f:id:trpg_yoshi:20210528193615j:plain

入力

今回は時間変動を扱うので、T ノードを入力に使います。
LogiX で時間経過で値を変動させたい場合は T ノードを使うらしいです。
これはワールドが生まれてからの時刻を吐き出します。Sin ノードや Cos ノードに渡すといい感じに振動する値が作れます。
T ノードは InputSinCos ノードは Math の中に入っています。
f:id:trpg_yoshi:20210528193651j:plain

他にも T*10, T/10, T/2 などのノードがありますが、今回はパラメータを後で変動させたかったので使っていません。

Rotation を変える1

CosSin の値を Pack xyz でまとめます。
Pack xyz はたぶん xyz のベクトルにまとめてくれるやつです。たぶん。
それを 180 倍して、From Euler で角度型に変換します。
ちなみに四則演算や比較演算子Pack xyz などは Operators に入っています。Math の中を探してぜんぜん見つからなくて泣きました。
From EulerMath/Rotation です。
f:id:trpg_yoshi:20210528193726j:plain

こうして出来上がった LogiX の出力をオブジェクトに繋ぎます。
DevToolTip を装備して、オブジェクトのインスペクターを開きます。その後、 LogixTip に装備を変えて、オブジェクトの名前をグラブしながらセカンダリーでインターフェースノードが開きます。
文章だとなんのこっちゃだと思うので、上記の動画などで確認してください。

インターフェースノードはオブジェクトのスロット(インスペクターの階層みたいなやつ?)やコンポーネントなどからだせるらしいです。たぶんですけどインターフェースノードを出せるやつはぜんぶ LogiX で弄れます。

インターフェースノードには色んな色や模様がついてますが、これらは同じ色・模様は同じ型らしいので、同じ色のものを繋げることができます。
弄りたい値の型を見て入力から LogiX を捏ねていく方が考えやすいかもしれません。

今回は Rotation を変えたいので、Rotation の場所に繋ぎます。繋いだときに線じゃなくて矢印になるんですけど、どういうやつなのかは知りません。
f:id:trpg_yoshi:20210528193748j:plain

愉快に回る箱の完成です。

Scale を変える

Position のときと同じ理屈で、いい感じの LogiX を繋いで出力を Scale に繋ぎます。Scale の型は3次元ベクトルっぽいので Pack xyz から直接繋ぎます。
Sin のままだと値域が -1 ~ 1 でダサかったので 0.5 ~ 1.5 の値になるようにノードを挟んでいます2+1 ノードは Operators の中にあります。
f:id:trpg_yoshi:20210528193925j:plain

色を変える

色を変えるために、マテリアルを作ります。DevToolTip を装備してコンテキストメニュー>新規作成>マテリアル>PBS Metallic を選びました。別に何でもいいです。
作ったマテリアルをグラブして、Box のインスペクターの中の Mesh Renderer コンポーネントの Materials (list) の中の枠にトリガーします。最初に入ってるマテリアルの上からセットしていいです。
これをせずに初期のマテリアルを弄ってしまうと、ワールドのデフォルトのマテリアルが変化してしまうらしいです。

その後は同様にマテリアルのインターフェースノードを取り出し、今回は EmmissiveColor に向けて値を作ります。
Color から Hue ノードを選びます。これは Float の入力から色相を作るノードっぽいです。Float ならなんでもよさそうなので、T ノードから直接繋いでみます。
f:id:trpg_yoshi:20210528194001j:plain

ゴキゲンに光り輝く箱の爆誕です。

速度を変える

このままだと一定の速度で動くだけのインテリアですこし面白くない(し、動くのが速くて目が痛い)ので、速度を変えれるようにします。

入力の T ノードに戻って、T から伸びてるノードの間に掛け算ノードを挟みます。そして掛け算を T 掛ける何かにしましょう。
LogiX では変数も扱うことが可能です。Variables/Storage から Float を選んで、掛け算ノードに繋ぎます。
Float ノードの初期値は0なので動きは止まってしまいます。)
f:id:trpg_yoshi:20210528194116j:plain

この Float ノードに対して、特定のアクションを行った際に値を書き込むように組んでみます。値を書き込む際に使うノードは Write ノード。Actions から取り出します。
Write ノードは入力の Pulse が来た時に、入力の値を矢印の先に書き込むノードらしいです。なので矢印を Float に繋ぎます。
f:id:trpg_yoshi:20210528194139j:plain

Write で書き込む値は毎回違う値にしたいので、乱数を使います。Math/Random から Random Float ノードを選びます。
このノードには入力が2つありますが、値域を決めるためのもののようです(大小はどちらでもよさそう)。今回は 0 ~ 1 にします。
f:id:trpg_yoshi:20210528194156j:plain

この状態で Write ノードの Pulse を押すと、押したときの乱数の値が Float ノードに書き込まれ、速度が変化できます。

グラブした状態でトリガーしたときに Pulse を送る

ここはぶっちゃけ人に質問して作ってもらった箇所なので、詳しい理屈はわかりません。繋いだものを並べます。

まず箱の Grabbable コンポーネントからインターフェースノードを取り出します。 そこから次を繋いでいきます。

  • Interaction/Grabbable/Grabbable Grabber
  • Slots/Get Slot
  • Slots/Get Active User
  • Input Devices/Controllers/Standard Controller (2つ)
  • Math/Max

f:id:trpg_yoshi:20210528194242j:plain

この順で繋ぐと、箱を持ってる人がどれだけトリガーを押し込んでいるかが拾えるらしいです。
ちなみに Standard Controller を2つ作っているのは、右手用と左手用らしく、どちらの手で握ってるかを把握する LogiX も書けるらしいですが、覚えてないそうでこの方法を教えてもらいました。
Standard Controller からトリガー時に Pulse が出る出力もあるらしいですが、バグりやすいとのことで押し込み時の率からやるのがいいそうです。

これを Pulse にするために、Operators の大なりノードを挟み、FlowFire on True ノードで繋ぎます。
Fire on True ノードは入力が True になったら Pulse を流すノードだそうです。Fire on True ノードから Write ノードへ繋いだら完成です。
f:id:trpg_yoshi:20210528194314j:plain

packing

箱と一緒に LogiX を保存するために、忘れずに packing します。
インベントリの Box - Parent を選択して黄色い星アイコンをクリックして子スロットを作ります。
Box - Parent - Child が作成されますが、わかりやすいように名前を変えます。logix とか。ついでに親も名前を変えておきます。眩しいので gaming box とかにしておきます。
logix をグラブした状態でコンテキストメニュー>パッキングルートに設定を選び、LogiX ノードに向けてビームが飛んでる状態でセカンダリーを長押しします。
LogiX が全部消えるまで繰り返します。

これができたら、gaming box を掴んでインベントリに保存しましょう。

遊ぶ

楽しい。

まとめ

Neos の記事はまだ少なそうなので、こんな感じで雑多な記事を書いて情報量を増やしていこうかなと思いました。初心者の気持ちになれるやつがあると嬉しいです。なお質。
おしまい。

躓いたところとか

Box にそのまま Grabbable 付けてたら掴めなくなった

値を変えてるとき(紫色になってる場合)は掴めないらしい。親を作って回避。


掴んでトリガー押したら2回 Pulse が流れるっぽい?

LogiX を出してると重いらしく、そのせいで処理がダブついてるんじゃなかろうか。パッキングして LogiX を消したらいい感じになった。

このノードどこにあんの???

誰かから NodeMenu+ を貰いましょう。検索機能が付いてるので便利です。
JP skill share World の複合ツールチップにあるマルチツールチップを装備して LogiX モードでノードブラウザを開いても出てきます。
f:id:trpg_yoshi:20210528194425j:plain

追記


  1. Rotation の回転を LogiX で組みましたが、 spinner コンポーネントというものを使えばもっと簡単にできそうです。後で知りました。

  2. Remap ノードを使えばもっと簡単に値の再割当てができました。