見出し画像

VRChatで作った傘worldの話


きっかけ

Atelier Yuikiの切子傘アセットが素敵だ。アバターに持たせる傘のギミックで愛用の球体関節人形アバター・マリオンに装備させて気に入っている。以前に作りかけて手が止まっていたアンブレラ・スカイ(小径こみちの頭上を開いた傘で飾って満たすようなやつ)を思い出し、この切子傘を使ってどうにか完成できないかと思った。

デテールのギャップ

ところが試してみると小路――路地のアセットと切子傘のデテールが釣り合わない。unityのasset storeで売られている歴史ある市街の路地アセットが傘に対して見劣りしてしまう。路地(array)アセットを三つほど買ってみて方針変更の必要を感じた。

傘は主役

そもそも見せたいと思ったのはこの切子傘のアセットだ。ならば傘を主役に他の要素は脇役にしてしまえばいい。そう考えたところで思い浮かんだのは鏡のような水面を飛び交う傘のイメージだった。切子傘アセットに含まれるのは25種類。水面に映るものを含めて50個の傘が舞うのは見映えがするのではないだろうか。

サイクロイド

ここで登場するのがサイクロイドだ。
"スピログラフ"という定規が小学生の頃に流行った。長方形のプラスチックの内側に歯車を刻んだ穴が空いていて、さらにその内側を小さな歯車が回るおもちゃだ。

これはトロコイドという曲線を描くための定規で、条件をさらに絞ったものがサイクロイドになる。サイクロイドは様々な場面に応用されていて、たとえば遊園地のコーヒーカップ遊具が当てはまったりする。
サイクロイドは数式で表すことができる。その何が良いのかというと、時刻の関数としてサイクロイドに乗った物体の座標を表すことができるという点だ。そしてVRChatではServerTimeという概念がある。同じインスタンス内で共有される時計のことだ。このServerTimeをキーにしてサイクロイドを描かせれば同期なしでworldインスタンスにいるすべてのプレーヤーに同期した動きを見せることができる。つまり、面倒くさい同期管理が要らなくなるというわけだ。
25個の傘それぞれに違うパラメーターを(固定で)持たせておけば、サイクロイドが傘を適度に散らしてくれる。円要素ひとつめの半径、ふたつめの半径、基本周期、位相。これだけを初期値として与えてやると、遊園地のコーヒーカップよろしくいつどこにどのカップが来るのか予測しづらいけれど遊具の外周の内側を幾何的に移動し続ける動きが与えられる。簡単。お手軽。手間も要らない。

サイクロイドな音楽

傘ワールドの試作udongraph

試しに傘を宙に舞わせてみた。悪くない。udon graphはサイクロイドのような簡単な数式でもノードが膨れ上がってしまうけれど、コードのミスタッチはないしフローも明確だ。一時間程度の作業で動くようになった。
この段階で"ワールド制作雑談会"イベントのワールド巡りタイムに試作品を見てもらった。
反応は上々だった。

  • 傘が綺麗

  • 巡る傘に掴まりたい

  • 音楽は?

傘に掴まるのは私もやりたかった。メリーポピンズみたいに!
音楽も付けたい。私のワールドはBGMを設定していないことが多い。特に理由があるわけではないけれどこの傘ワールドには欲しいと思った。そう――サイクロイドで円を描く動きを見せるなら音楽も円を意識したものが良い。輪舞曲? 確かに日本語では"輪"だけれどロンド形式は循環を示しているのであって周期性があるという以外に円との関係はない。遁走曲(フーガ)も別に遁走のイメージがあるわけでなく楽譜の上での作曲ルールを示す用語だ。日本語訳の音楽形式名はいったん忘れよう。
サイクロイドの動きに近いのは恐らくダンスとしてのワルツだ。舞踏室を円を描くように巡りながらパートナーとも小さな円を描く。ならば音楽もワルツで良いのではないか。ヨハン・シュトラウス二世にはずばり"Cycloyden"というワルツもあったりする。
ワルツといっても候補は山ほど。
ここでキーになったのは"鏡のような水面"を設定していたことだった。この水面を滑るのであれば、答えはひとつ。Émile Waldteufelの"Der Schlittschuhläufer"――スケーターズ・ワルツだ。傘に掴まって浮かぶというギミックとの釣り合いではメリーポピンズの"Singing in the Rain"も魅力的だが、サイクロイドの幾何学の美しさと雨の中をあえて濡れながら歩くエモさとは調和しない気がしてスケーターズ・ワルツにした。

次はギミックだ。
動き回る傘に掴まれるようにするために以下の要件を設定した。

  • interact→useではなく手を伸ばしてgrabで傘に掴まる

  • 傘にぶら下がれるのはgrabし続けている間だけ

手を離せば落ちる。この当たり前のことを仕込みたかった。
傘をgrabしている間だけ傘の子に設定したVRC Station(のStation Enter Player Location)に入るにはVRC Pickupを使うのが早道らしい。ところがこれが難物だった。傘に掴まった途端にプレイヤーが傘ごと高く遠くに飛んで行ってしまうのだ。高速回転を伴って。

空の彼方へ

『雨に歌えば』どころではなく『オズの魔法使い』のドロシーさながらである。

どうやらPickupとStation、Transform.setPositionの組み合わせは難があって、grabした手を正しく傘の柄に置き続けられるようEnterPlayerLocationを調節し続けようとすると発散してしまうらしい。RigidbodyやPickupの設定を様々に変えてみたりudon中で工夫してみたりしたけれど効果がない。途方に暮れた。

AIにお伺い

困ったときはAI頼み。Grokに訊ねてみた。
起きている問題を具体的に書いて改善法を教えてくれ、と。

Grokの回答のほとんどは実施済みの対策だった。ひとつだけ試していないものがあった。

・VRC_Pickupと座標競合:
  ・Allow Manipulationがオフでも、VRC_Pickupの内部処理が位置を一時的に変更する場合がある。LateUpdateで座標を強制上書きすることで解決。

Grokとの対話ログ

試してみた。
動いた!

UpdateイベントをLateUpdateに入れ替えて解決、かと思いきやうまく行ったのはunityエディタ上のエミュレーターとデスクトップ環境だけ。けれどこれが大きなヒントに。
傘の座標計算をUpdateイベントに、Stationの位置調整をLastUpdateイベントに置き直してみると想定通りの動作になった。なったのだが、間欠的に動作がおかしくなる。これがどうしても解消できない。
うまく動かないのは「grabしている手と傘の位置関係の微調整」という細かな点なので今回はその機能を見送ることにした。

壁2

udonの挙動がどうも変だ。シンプルなpickupやstation単体での挙動と併用している傘worldでの挙動がかなり違う。ということで悩んでいたところでVRCのフレンドに教えていただいたことがある。pickupとstationのcomponentを同じオブジェクトに付与するとおかしくなる、というやつだ。pickupもstationもcolliderを必要とするのだが同一オブジェクトで両componentを使用するとひとつのcolliderを共用する形になる。これがまずそうだ。
というわけでpickupとstationを別オブジェクト(empty)にした。具体的にはpickupをstationの子オブジェクトに分けてみた。
getComponentsInChildrenを使う構造依存のアルゴリズムがあったり、ついでとノード数が嵩みすぎたudongraphを複数に分割したりしたために思ったより作業量が増えてしまったが効果は歴然。ナンデコーナルノ?という怪しい挙動が一掃できた。
もっともその"怪しい挙動"のひとつでそのための挙動を組んでいないのに傘が(ローカルでだけ)手の細かい動きに追従するというものがなくなってしまったので現在追従させるための処理を仕込んでいる。

worldの外見も大きく変わった。昼夜を動的に変化させるギミックを採用し、ガゼボや外周の建物を撤去して思い切りシンプルに。ガゼボのあったworld原点には籠を置き、傘たちはそこでの休憩と広く動き回るモードの二つの状態を遷移できるようにした。

籠の傘


また事実上の標準となりつつあるVRC Light Volumesのver.2で利用が容易になったPointLight機能を使って傘の模様の色影(というか照明)を落とすようにした。上画像の通りcookieで落とした色影が赤い傘のものばかりになってしまったりで設定と食い違っていたり。原因調査中。

まだしばらくかかりそうだけれど近日公開予定。

公開

近日公開予定と書いてから半年が過ぎてようやく公開できた。

この間、躓いていたのは……

  • VRC Light Volumesのbug

  • pickupとstationの干渉

  • udon graphのノード数上限

  • 景観の変更

  • ドームスクリーン

等々。

鳥籠切子の円舞曲

画像のように背景を一新した。テラジェン・スタジオ様の『空の円卓』というworldアセットを導入。切子傘ワールドの制作中にこの『空の円卓』のサンプルworldが公開されて一目で「これは合う!」と思えた。円舞曲ワルツは円形のステージとも相性が良いはず。
最初にイメージしていた"鏡のような水面"は鳥籠の下の小さな泉に痕跡を残すのみとなった。
鏡の代わりとなったのはVRC Light Volumesによるカラーの影。これはVRCLVのサンプルの中にある懐中電灯のcookieに色付影画像を入れただけ。VRCLVのV1.0の頃はcookieのtexel配列参照がバグっていてうまく動かなかったが現バージョンでは問題がない。簡単で綺麗なのでお勧め。

円舞曲はyoutube動画から建物の外の半球ドームに映しているがネット状況によって再生できたりできなかったりしているようだ。

現時点では見送った機能もあるが問題の解決とともに少しずつ機能を増やしていけたらと思う。

いいなと思ったら応援しよう!