春夏秋冬ワールド

最近わりと雰囲気系ワールドをアップロードしてました。

まぁなにかというと結構ずっとギミックファーストでワールドを作ってたので
それ以外のいわゆるチルとか撮影とかそういうのに使えるワールドを作ってみたくなったわけです。

とりあえず春夏秋冬をテーマに1季節1ワールドを目標にアップロードしてました。

春夏秋冬にしたのはどちらかというと途中で終わらせないための縛りプレイでもあるのでですが。

その振り返りみたいなやつです。

春: 桜の園

https://vrchat.com/home/world/wrld_78e15950-bd94-469a-83cf-8de6287fc15e/info

春

一番最後に作ったワールドです。夏から作り始めたので春が最後になりました。

桜の木があるだけです。

プレイヤーがLeftすると桜の木になります。
いっぱい人が来て、いっぱい人が去っていくと、一面の桜吹雪が舞います。
嬉しいですね。

一応位置を記録してLateJoiner対応しています。
なんか、モデル作って、なんか名前とか出るようにしたら、汎用アセットになったりするかな。まぁやらないですが。

あと急に桜が出るのも変な感じだったのでliltoonのdissolveを使っていい感じに出るようにしました。


夏: 夜の踏切

https://vrchat.com/home/world/wrld_52294fc8-bd68-41ef-950c-c8f581d62107/info

夏

そもそも思い至ったやつです。
単純にある真夏の日に深夜寝付けなくてお腹空いたので ゆで太郎 うどん屋 に向かってたのですが、ふと踏切を渡ってる時に見上げた空が綺麗だったので「これをワールドにしたい」と思ったのがきっかけです。

雰囲気ワールドなので出来るだけ自分でギミックを組んだりコードを書いたりする作業を排除して、アセットストア及びBoothでの購入物を組み合わせて作ることを目標にしました。

アセット選定とワールド構築合わせて3時間程度で出来上がりました、うどん食ってた時間含めても5時間くらいかな。
かけた時間のわりになかなか満足のいく感じに仕上がったと思います。
感情って鮮度があるので、そのままアウトプットできたのは良かったと思ってます。

チルワールドなので最低限のチルっぽいもの(要出典)を置きました。
(VideoPlayer,Mirror,Pen)


秋: 円焚 - entaku -

https://vrchat.com/home/world/wrld_6bc8e597-e487-4739-ab56-7ef81a8653c9/info

秋

1季節1ワールドとか言い出したはいいがもうね、何も浮かばん。別にふとした日常生活で感情に浸る季節の出来事があるかといわれるとそうでもなく、わざわざ旅行みたいなことするのも意味不明だし。

VRChat内にも結構季節があるなと思ってて、やっぱNewワールドとか巡ってると季節っぽいものがあるなぁと思うし
ソーシャルでフレンドのいるワールドもなんとなく季節感を感じるなって。

そんな中であるキャンプ的なワールドに行った際に、焚火を囲むように人がいて
VRChatって結構壁に沿って座ることが多いじゃないですか
つまり中心にミラー or 動画プレイヤーがあれば人が中心を囲うように配置されるのでは?と閃き
そこからワールドに着手しました。

ある意味感情敵に作ってますが前のとは全然動機もコンセプトも違うし、取ってつけたような季節感なので仕上がりは少し微妙ですね。
そもそもギミック寄りのコンセプトだけあってワールド全体像の着地点が無いので「なんとなくそれっぽい」が仕上がりの限度になってしまうんですね。

以下なんか解説みたいなの

焚火

焚火です。アセットそのまま利用です。
ワールドの季節感の趣旨でありワールドの中心となる記号です。

動画プレイヤー

焚火の上に置いてあります。
プレイヤーの位置を計算してスクリーンがプレイヤーの方向を向くようになってます
動画プレイヤーの特性として「他人と位置の同期をしなくていい」「同じ空間で同じ動画を見ることが出来ればいい」というものがあると思ていてこうしてみました。

ただ、焚火の上に置いたので燃えてるように見えます。これは正直失敗寄りです。

ミラー

焚火の位置とプレイヤーの位置を計算してその中心地点にミラーを配置し、プレイヤーの方向を向けています。

ミラーは動画と同じく位置の同期は不要で、なんなら自分だけ見えてても問題ないという特性があると考えてます。

動画と焚火を見たいだろうと思い、プレイヤーだけがミラーに映ります。
結果としてプレイヤーが燃えているように見えます。ミラーって難しいんですね。

また、ミラー自体の位置と角度が移動しているため、常にミラーの中心がプレイヤーの映る位置になり移動しながらミラーを見ると少し気持ち悪いです。ミラーって難しいんですね。

メニュー

ミラーもビデオプレイヤーも中心にあるため、壁が不要と思ったのでこのワールドには壁が無いです
壁が無いことによる弊害はもちろんあって、いわゆるJoinログとか、コントロール系のパネルとかそういうのって壁が適した位置なんですよね。

案としては

  • なんか建物っぽいものを用意して中に入れないけど外側の壁にそういうコンポーネントを配置する
  • 看板みたいなのを置く
  • ワールド端に見えない壁はあるのでそこに配置する
    とかは考えましたが、まぁ結局壁が無いのでなんか分かりづらいし、看板もあんまり意味不明だし、建物っぽいものもあまり説得力なくてやめました。

まぁ結局悩んだ末にVRChatのメニューを開くと連動して出てくるメニューみたいなのを自作しました。
それだけです。これが良かったかというとそうでもないです。ぱっと見で見渡せるワールドなのにそこに無いのは”無い”って思われるし、急に出てこられても意味不明だし、まぁ難しいですね。悪くもないんでしょうが。

逆に言うとやっぱよく使われてるスイッチ類(Lura’s Switchとか)は偉大ですね。
初見でも一度使えば機能が分かり、別のワールドでもその知識が生きる、素晴らしいです。


冬: まだ作ってない

嘘、まじでなんも思いつかなかったのでBlenderでワールド作ってみたかった欲求を満たしつつ冬ということにしました。なので雪が降ります。

https://vrchat.com/home/world/wrld_4d41217b-b8b7-487a-85cd-05307c779b84/info

冬

Blenderでガワを作った点、雪が降る以外に特にないです。
ホームワールドにもしようと思ったのでVideoPlayer周りがホームワールド仕様です。
最近(2025.04.28現在)リダイレクトでの動画の再生が調子悪そうなのであんまり使ってないですが。

窓から見えるだけじゃ物足りなかったので雪を浴びれる空間も作りました。

そういえば個人的な感情なのですが、雨が降ってるけど窓から雨が降ってるのを見れるだけのワールドがあんまり好きじゃなくて(憂鬱になる)。ただ見るだけは無くて外に出て雨の降ってる空間に行けるワールドはどちらかというと好きです。
あまり言語化できてなくそう思うだけなのですが、なんか雨に打たれてると憂鬱な気持ちを雨が肯定してくれるみたいで好きです。

まぁなのでたまに雨も降ります。

Readroom についての雑記

Readroom-りどるーむ-

Readroom

Readroom

※※※この記事にはネタバレが含まれます※※※

はじめに

Readroom
りどるーむ

謎解きも出来るChillワールド、だと思います。

ワールド名は”Riddle” + “Room” から来ています。
単純にRiddleRoomでも良かったのですが、明らかに謎解きワールドっぽい名前になるのは避けてひとひねりしてます。
(あくまでもChillワールドなので)

一説によると「Read the room」で「空気を読む」という意味になるようで、謎解きであることを読み取るというニュアンスがあるとか

また別の説では各開発者の名前のイニシャル

R: ヒャクアシさんの別名義のイニシャル
e: 円フツさんのイニシャル
a: aki_lua87のイニシャル
d: らぃむさんのIDのイニシャル(dimebag29)

だとか。


元々は「ギミック製作者何人かで謎解きっぽいの作って持ち寄れば謎解きワールドができるんじゃね?」みたいな雑談から始まったような気がします。

Kano’s Lake をみんなで解いた際にぽっと話が出始め
個人的にもApril Waters を訪れた際に「和み雑談する人」と「謎解きを進める人」が共生できるのいいなぁと思っていたので
Chillワールド+謎ギミックみたいな方針で作成が始まりました。

まぁ、Chillワールド成分は全部円フツさんにやってもらったわけですが
まぁ、めっちゃいいワールドになっててすっげえなと思いました。
個人的好きポイントは寝室のスライドドア閉めるやつです。

以下、aki_lua87作成部分。

謎1「神社」

神社

神社


利用アセット

神社は別ワールドでフラグを立てることで回答が可能になるというギミックを用いた謎解き(?)です。

神社自体は特に何か意味がある物ではなく単純に景色のプラトーが埼玉って聞いてなんとなく武蔵一之宮氷川神社が浮かんだので神社にしました。

最初はホラーワールド風にして1人で来た人を恐怖のドン底に落としてやろうかとも思ったのですが
Chillの部分が想像以上のハイクオリティに仕上がっていくのを見て流石に壊すのは如何かと思い変更しました。

入室上限が1人なのはその名残でもあり、インスタンスに人を残すメッセージでもあったのですがあまり有効には働かず失敗だったかな。

折角部屋っぽいので「ベランダから見えるランドマークポイントに訪れる。」というようなフレーバーもあります。
ベランダからレイを飛ばしてワールドに入るみたいなとこも気に入ってます。
(が意外と知られて無い機能だったかもしれない)

謎自体は「ワールドを跨いだ謎解き」「答えが毎回変化する謎解き」になります。

  1. ワールドA(Readroom)にてStringLoaderをコール、インスタンス固有のコードを受け取る
  2. インスタンス固有コードは同期変数で同期
  3. ワールドB(神社)にて固有コードより推測される解除コードを入力しStringLoaderで送信
  4. ワールドAの解答入力時に解除コード入力済みかのフラグをStringLoaderで確認し解除済みであればクリア

となります。

草案図

草案図

インスタンスの固有コードの概念については「謎解きワールドで謎の答えを教えてもらう」のカウンターにならないかと考えて「答えじゃなくて必ず解き方を教えてもらわないと解けない」を目指しました。
まぁこれ自体はStringLoader使わずにワールド内で生成しても馴染事は出来ますが。
Webを使う利点はチェックすることで被り無しで発行できることですかね・・・

ただいろいろミスリードさせてしまったみたいで…ちょっと混乱を招いちゃったかなとは思ってます。
ほかの謎はギミック自体が謎であるのに対してこれはギミック自体は初見だとギミックでもなんでもないのでちゃんと謎解きに落とし込むまで練り上げる必要があったかなとも。

StringLoader呼び出し用のVRCURLはプログラム上で動的に作成はできないので
予め発行可能な固有コード全通り分のURLを生成して変数で管理してます。

結果としてトータルで10000ケースでかつ状態管理用に数パターン必要なためVRCURLを管理するだけの数万行のU#が生まれてしまいました。

正直受け入れられるかも含めてプロトタイピングみたいなところもあり細かいところが雑なのですが
まぁこの時はこれでうまくいくと思っておりました。
がリリース後ちょっと色々問題が発生して・・・


アクシデント1 リソース枯渇

これは見積もりと設計が甘い話。

ワールドBでの解除コードは容易に復号できる形でURLに辿り着きたかったのでそのまま入力値≒固有コードでやってたのですが
想定を大幅に超える方々にワールドを遊んでいただいたことで用意された固有コードをほとんど食い潰す自体に陥りました。

固有コードを食い潰した状態だと当人としては間違った解除コードを入力しているにもかかわらず
他インスタンスの解除コードと一致してしまった結果、ワールドBを間違えた解除コードで突破可能になってしまってました。
(他人に解かれる可能性はあるとは思ってましたがまぁ1000コード程度なら偶然当たることも無いだろうとタカを括ってましたが、誕生日のパラドクスじゃないですが母数が増えるほど当たってしまうのでそもそもそれ自体が間違い)

さらに二次被害として解除コードの利用回数に制限を設けていたため
偶然にも解かれてしまったインスタンスが進行不能になってしまうということにも。

誰かが総当たり試みると終わってしまうので、そもそも仕組みがよくなかったです。

問題発生後に急遽解除コードのパターンを1万通りから100万通りに拡張しました。
(ギミックの根幹を変えるわけにはいかないので、偶然の一致の抑制+総当たりに挑む気力を無くさせるの効果を期待)

固有コードは前述のURLの関係で拡張できなかったため多少無理やりですが、現在遊んでいるワールドに影響がないようにワールドA,ワールドB,StringLoader受付サーバを更新する必要があり少し大変でした。。。
(気づいた方もいるとは思いますが、途中でDescriptionが変わったり、問題の数字の桁が増えたのはそのためです)


アクシデント2 VRChat外部よりアクセス

こちらは設計とセキュリティが甘い話。

今回用意していたURLはクエリパラメータで固有コードを判別し処理していたのですが
固有コードに特に暗号化も設けず、またサーバサイドもリクエストのチェックなど実施せず全て受け付けるようにしていました。

なので・・・といいますか、VRChat外部より固有コード発行および固有コードを使った解除を網羅的に呼び出されてしまう事態が発生しました。
サーバは受け付けたもの全て処理するので、不正なレコードをたくさん作られてしまいました。(テヘペロ

これは前述のリソース枯渇問題にも影響し、固有コード枯渇や進行不能インスタンスを作り出すことになってしまいました。

当然といえば当然ですがStringLoaderで状態を管理する場合はパラメータの難読化やアクセスを弾くような仕組みが必須ですね。
後付けでやりましたが最初からやっとけよという話。


順位システム

初日クリアインスタンスにて撮影、なんかバグって鍋の順位が出てない

初日クリアインスタンスにて撮影、なんかバグって鍋の順位が出てない

5日目クリアインスタンスにて撮影、本当に滅茶苦茶解かれたと思う

5日目クリアインスタンスにて撮影、本当に滅茶苦茶解かれたと思う

謎ではないですが自分が担当した部分なので。

遊んでくださった方は体感したかと思います。このワールドには「順位」があります。
各問題ごとのクリア順位と全体のクリア順位のやつです。

神社が「ワールドを跨いだ」ギミックだとするとこちらは「インスタンスを跨いだ」ギミックのようにイメージしてます。
単純に数字をインクリメントしるだけですが……

インスタンスをチームのような概念と考え他のチームと「リアルタイムで競い合える」もしくは「1位を目指す!!!」のようなモチベーションになってほしくて作りました。
(いい感じのUIにしてくれたのは円フツさんです。マジで感謝)

元々「インスタンスを跨いでゲームをする」みたいな概念はたまに考えてて ワールド間対戦リバーシ のようなものを作ったこともありました。
(まぁこれは対戦相手がリアルタイムでいないと遊ぶことすらできないのでよっぽど流行らないと成り立たない)

順位を表示すること自体は結構成功だったかなと思ってます。
Twitter(現X)に順位のスクショを載せてくれる方も結構いて嬉しかったですね。
(なんかバグって表示されて無かったりも多々あったようですが……)


その他

実はキューリストにURL入れるとタイトルに変換される

URLを入れてしばらくするとこんな感じに、ちょっと便利

URLを入れてしばらくするとこんな感じに、ちょっと便利


自作ギミックとかではなく Iwasync のキューリストと YTTL を繋げてるだけです。



おわりに

制作物の8割くらいは円フツさんなのでだいぶ何もやってないですが
やってて楽しいワールド制作でした。

色々問題もありましたが、たくさんに人に遊んで頂いてよかったです。

あと鍋は俺もこんなん解けるわけねえだろってずっと思ってます。

readroom2とかは多分ないです。

おわり