VRChatにみんなで遊べるマインスイーパーワールドを作ってみる

UdonSharpの同期変数の仕組みが分かってきたので、
同期を活かした新しいワールドを作ることにしました。

ジャンルとしては仲間同士で遊べるようなゲームワールドを作りたいと思い、
繰り返し遊べる要素があって、
みんなで遊べるゲームとはどんなゲームだろうと考え、
思い浮かんだのが少し古典的なゲームですがマインスイーパーでした!
そんなこんなでマインスイーパーのVR化を進めていきました。

マインスイーパー自体のプログラムは、
だいたい想像することができましたが、
ググってみるとたくさんコードが転がっていたので、
ゲーム部分は想像していた処理とネットの情報を組み合わせながら、
こちらはおおむね詰まることなく完成させることができました。

基本的にはそのブロックが爆弾かどうか、
爆弾でない場合周囲に爆弾があるか、
あれば数字を表示して、なければ周囲のブロックに対して再帰処理を行う。
こんな感じのロジックですね。

そしてしっかり考えなければいけないのがUdonSharpのクセの強い同期処理です。

同期の方式としては基本的には以前世代別交流用ワールドに設置した
入室者カウンターと同じ方式を取り入れました。
同期は同期変数を用いて、
更新は全てオブジェクトオーナーに移譲する同期方法です。

参考)世代別交流用ワールドに入室者数カウンターを設置する

複数人でゲーム参加しようとした場合、
あちこちでブロックを消したりすることを想定すると、
排他的な処理は必須となります。
オブジェクトオーナーに同期変数の更新処理を集中させると、
通信のラグがどうしても生まれてしまうのですが、
ゲームの性質上、多少のラグがあっても確実に排他できる方が良いと考え、
この方式に決めました。

同期変数を利用して、
複数のユーザが同じようにゲームを進行できるようにするためには、
状態管理がとても大事で、
大きく「ゲームの状態」「設定の状態」「ブロックの状態」
この3つの状態をコントロールしてゲームの進行を維持することにしました。

ゲームの状態
設定、ブロックの状態

そして設計を実装に落としていくことで、
ゲームが形になっていきました。

CyanEmuでデバッグもしつつ無事に完成と思い
いよいよVRChatへアップロードして動作確認をと、
アップロードしたワールドへ移動しようとしてみたのですが、
ぜんぜん読み込みが終わらず、、、
真っ暗な画面が延々と続く状態に、
VRChatはパフォーマンス系の制約も結構厳しいようで、
これまでもマテリアルの画像を圧縮して容量自体は削減したり工夫はしていたのですが、
実装面でも気をつけるべき点がいろいろとあるようです。

まず取り組んだのが

「脱string型」

string (文字列)は定義しているだけでもGC Allocを発生させるということで、
stringを使わないで実現できる部分は可能な限り他の型に変えたり、
処理の見直しを行いました。

(参考)こちらの記事参考にさせていただきました。
https://qiita.com/toRisouP/items/16bd06aa303a1bb1a747

でも結果は変わらず、、
次に取り組んだのが

「同期変数のサイズ削減」

同期変数は更新をかける度に通信が発生し、
ネットワークもそれほど潤沢では無いようで、
同期変数の通信量削減はとても大事なポイントのようです。
ということで、整数型の同期変数は出来るだけ
int型ではなくbyte型に変換していきました。
最近は通信量意識して実装したりとかあまりしていなかったので、
久々に型の重要性を再認識させられました(笑)

でも結果は変わらず、、
その次に取り組んだのが

「手あたり次第怪しい実装を外してみる」

もう原因が読めなかったので、
とりあえず怪しい実装やゲームオブジェクトそのものを削除してみたりと、
手あたり次第ですが、
症状改善するポイントを切り分ける作業を試みました。

特に怪しいと考えていたのが、
ゲームの設定上、マス目を16×16にした場合にブロックの数が256個になるのですが、
当初それぞれのブロックに対して、
どこからでも「破壊」と「フラグ」が実行できるようにと、
ボタンを5面に設置していました。
これだけでボタンの数が2,560個、
全部のボタンにインタラクトできるように
Udon Behaviourコンポーネントを割り当てていました。
(リンクしているスクリプトは同じものでしたが)
この辺りが読み込みを遅延させているのではと考え、
コンポーネントを外してみたり、
SerializeFieldを使っていたので外してみたり、
ブロックのオブジェクトの数を減らしてみたり、
ボタンを5面設置(5組)じゃなく1組にしてみたり、

と試行錯誤をしていく中、
結果ボタンの数を減らすことで事象の改善が現れることが分かりました。

「対策」

対策としてはシンプルにブロック上面に「破壊」と「フラグ」ボタン1組を設置する形に変更して、
何とかゲームが読み込まれる状態に改修することができました。

ボタンの組数削減

それでも他のワールドに比べると読み込み時間は遅く、
根本的な原因は特定できていないので、
これは今後の課題かな、

最後にパフォーマンスで苦労しましたが、
何とか対策することができ公開に繋がげることができました!
まだまだ知れたことは断片的かもしれないですが、
毎回いろいろ障害にぶつかっていて、
なかなか勉強させられますね。

Minesweeper for VRChat ⁄ バーチャルマイスイ

1人で黙々と挑戦しても良し、仲間とわいわいと楽しんでも良しのVRマインスイーパーです。
ぜひぜひ遊びにきてください♪

ワールド:Minesweeper for VRChat ⁄ バーチャルマイスイ

世代別交流用ワールドに入室者数カウンターを設置する

前回の記事で同期変数の実装方法がだいたい理解できて来たので、同じくVRChatにアップロードしていた世代別交流を目的としたワールド「世代別だんらんステーション」に入室者数を確認することのできるカウンターを設置しました。

このワールドには世代別の部屋と大きなホールを設置していますが、ワールドに入ってから、ワールド内にユーザがいることは分かっても、どの部屋に人がいるのか知ることができず、部屋まで行ってみる必要があったため、改善したいなと考えていたポイントでした。
(結構広いので、この中をどこに人がいるのか分からないまま行き来するのはなかなか煩わしいですよね、)

世代別の部屋とホール

ということで、スポーンの位置を少し変更してカウンターを表示するためのパネルを設置。
それから各世代別の部屋とホールにボックスコライダーを追加しました。

入室者数カウンター
コライダー追加

あとはUdonSharpを使ってカタカタとコーディング。
今回は前回の巨大迷路とは違って入室者のPlayer IDをシンプルに一元管理したいというのもあって、排他的に制御できるように同期変数の更新は各プレイヤーにオブジェクトオーナーを割り当てて更新させるのではなく、すべてオブジェクトオーナーが更新する方式にしました。
(同期変数は更新反映にラグがあるらしいので、注意しなきゃいけないポイントですね)

大まかなシーケンスとしては以下の様な感じ、入室も退室も基本的にすることは大きく変わらず、今回はだいぶシンプルなコードで実現できました。

入室シーケンス
退室シーケンス

ポイントとしては、
①入室、退出のイベント検出
 入室:OnPlayerTriggerEnter
 退室:OnPlayerTriggerExit
 ワールド退出:OnPlayerLeft
②オブジェクトオーナーが同期変数を更新および同期実行
 同期変数:OnValueChangedのManual同期
 同期実行:RequestSerialization
③カウンターへの反映
 オブジェクトオーナー:ローカル反映
 その他のプレイヤー:OnDeserialization呼び出し時に反映
という感じかな。

ということで、無事に実装アップロードを終えて、カウンター表示できるようになりました!

カウンター動作確認

ただこのワールド、アップロードしたもののVRChatにはCommunity Labsという審査を通すというステップが存在し、まだまだ通過できておらず、これがなかなかのハードルのようです。
ちゃんと公開したワールドを楽しんで貰えるようにするためには、そもそもコンテンツとして求められているワールドなのかというのもありますが、たくさんの人に訪れてもらえるようにコミュニケーションを密に行うこととブランディングを行うことが肝になるのかなと、こちらはまた大きな課題ですね。

もし興味を持っていただけたらぜひぜひ遊びに来てください!
ワールド:Generational Exchange Stations ⁄ 世代別だんらんステーション 

VRChatで同期変数を使ったゲームギミックを実装する

これまでcluster上で制作していた巨大迷路を、プラットフォームを越えてVRChatでも公開を開始し始めました。

VRChatにはUdonというビジュアルプログラミング環境が用意されていますが、それをUnity C#のようにスクラッチに実装することの出来るudonsharpというコンパイラが存在しているということで、少し勉強がてらプレイヤー間で同期可能なゲームギミックを実装してみました。

まず最初にプレイヤー間で同期を取った処理を行うということはどういうことなのか、VRChatの仕組みそのものが分かっていなかったので、VRChatのリファレンスを読んでみたりWeb上をあさっていろいろ調べるところから始めて、
なかなか情報は少なくいろんなサイトをあさりましたが、ハツェさんという方の「ハツェの真時代傾向璋」というサイトがとても詳しく書かれていて大変お世話になりました!ほんと感謝ですね☆

そして今回ゲームギミックとして実現したかった機能としては、
① 参加ボタンで迷路ゲーム開始
② 各チェックポイント通過でチェックポイント毎にアバターの頭上へアイコン点灯
 (他プレイヤーからも見えること)
③ ゴール通過ですべてチェックポイント通過できていない場合はヒント表示、
 完全にゴールでゴール用のオブジェクト表示
④ リセットボタンで迷路ゲームを初めから再開
⑤ 終了ボタンで迷路ゲーム終了
⑥ ゲームの情報を参加者一覧ボードで表示
 (他プレイヤーからも見えること)

と、だいたいこんな感じ。

学んだ情報を踏まえて、
VRChatのプロセスとしては基本的に各ユーザの端末にクライアントが存在していて、ワールドを稼働させるためのプログラムをダウンロードした上で、あくまでローカルで稼働しているということ。
各ユーザ間で実現可能な同期処理には制約が多々あり、プリミティブな型でないと同期できなかったりするということ。
などなどの情報から、状態遷移を整理して同期する情報を絞って今回は文字列の配列を用いた状態の同期を採用しました。
ざっくりな方式イメージとしてはこんな感じで、
おおまかには、ユーザのアクションから状態を更新して、更新を検知したらオブジェクトへ反映するという流れです。
※イメージは想像も含まれているので誤っていたらすみません、

方式イメージ
概要シーケンス

ポイントとしては、
① OnValueChangedという同期変数の仕組みの採用(Manual同期)
② 同期変数を扱ううえで重要な制約となるオブジェクトのオーナ権を付与するためのSetOwnerの呼び出し
③ 同期変数を同期するためのRequestSerializationとOnDeserializationの呼び出し
のあたりかな。

そして無事実装を終えて実現したかったギミックを完成させることができました!
なかなかudonの開発は難しいと聞いてたのですが、同期のデバッグとか簡単にできないので無駄に取られる時間が多いなと実感します、、
とはいえ、いろいろと学ぶことも多く次にやってみたいことも出てきたので、また次の試行錯誤始めていきたいと思います。

参加、リセット、終了ボタン
チェックポイントと通過アイコンの点灯
参加者一覧表示ボード

作成したワールドは現在コミュニティーラボに登録中となっています。
VRChatは公開ワールドとして全ユーザから見えるようになるためには、このラボで一定の基準を満たす必要があります。
基準は明確に公表されていないようですが、ワールドに訪れた人数(Visits)やお気に入り(Favorites)登録者数が影響しているらしいので、ご興味があればぜひぜひ遊びに来てください!!

ワールド : 懐かしの巨大迷路

世代別交流ワールドを作ってみる

ということで、
巨大迷路に続いてclusterに新しいワールドを作成してみました。

名前は「世代別だんらんステーション
ソーシャルVRをちょこちょこ始めて感じるのは、
やはりまだ利用している人の規模が小さいことと、
匿名性が高いというのが仮想な世界では良いなと感じる反面、
だれがどのくらいの年齢層なのか分からないので、
いきなり話に入るのをためらってしまうな~と感じていること、

近い年齢層の人たちと交流できる場所があったらいいんじゃないかと
年齢別交流を目的とした空間を作成してみました。

全体

ちょっと宇宙ステーションの様な、
SF的なテーマで自由に空間を繋げて、
全5階層で部屋は10代から60代までの6部屋、
それからフリースペース的なホールなども作っています♪

フリースペース(世代を超えた交流に)

こんなのあったら面白いんじゃないかと、
状態をアピールできるような立札や、
だんらんの雰囲気が出るように飲み物ギミックなんかも作ってみました。
のんびり椅子に座りながら
おしゃべりしたり、
話を聞きながらROMったり。

寝落ちしても安心

階層の移動には螺旋階段を用意していますが、
階間を簡単に移動できる転送装置も作りました☆

ボタンを押したら瞬間階移動

WEB2.0と言われる時代がはじまったころ、
静的なコンテンツだけでなく、
チャットという双方向でコミュニケーションが出始めた時は、
やってるひとは物好きがほとんどで、
なかなかおおっぴらにチャットやってるよと言い難かったり、
当時はなんかやっていることが恥ずかしく感じたりもしていました。

WEBカメラをつないで仲間の顔を見ながら毎日のように
夜な夜な盛り上がったりしていたな~と、

そんなチャットやWEBカメラでのコミュのケーションが
今では仕事でも普通に使っていたりと
一般的なコミュニケーションツールにまでなっているんですよね。

VRというコミュニティも当時のそれに近いのかなと感じる今日この頃、
今は少しでもこんなコミュニティがもっともっと広がっていったらいいなと、
盛り上げるため、いろいろ楽しいこと発信していきたいですね!

展望台エリア増築

clusterで制作している巨大迷路のワールドに
新しく展望台エリアを建設しました♪

展望台

木造の地上20mの展望台です。
実際にはありえないような建築物ですが、
VRの世界では想像をそのまま形に出来ます☆

Unity建築中

螺旋階段を上っていくと、
展望デッキからは巨大迷路も見下ろすことができます!

展望デッキ

そして巨大迷路と言えばバブル時代、
ちょっと遊び心に動くものを取り入れてみたいと思って、
上空に飛行船を飛ばしてみようと、
簡単ですがモデリングから作成して
飛行船を追加しました!

上空を旋回する飛行船
工作レベルですが飛行船を作成

現在もいろいろと試しながらあれこれ改良進行中です☆

懐かしの巨大迷路

懐かしの巨大迷路を建築

最近ではなかなか見かけることが少なくなってしまった、
巨大迷路をVRの世界に建築しました♪
アップロード先はまずはスマホからも気軽に遊べそうということで、
clusterにあげてみました!

巨大迷路で自撮り

建築の大まかな流れとしては、

1.設計
設計ツールは持っていないのでExcelを方眼レイアウトにして
建材の寸法の決定や、迷路のレイアウトを作成。

2.テクスチャ作成
PhotoshopやExcelを使って、建材や地面のテクスチャ、
案内看板などのデザインを作成。

Photoshopでテクスチャ作成中

3.モデリング
blenderを使って、設計に合わせて建材を作成。

blenderで建材モデリング中

4.組み立て
unityを使って、作成したモデルを設計した
レイアウトに合わせて配置と組み立て。

Unityで配置中

育児や仕事の合間時間での作業でしたが、
構想から初版アップロードまで約3日ほどの作業でした。
(現在も徐々に改良に改築は進めていますが)

本来であれば広大な土地が無いと立てられない巨大迷路も、
VRの世界であれば何もないところから作ることができます。
ツールもだいぶ進化していて、
導入障壁低く感じますね!

PCやVRゴーグルだけでなく、スマホからも遊ぶことができるので、
ご興味のある方はぜひ遊びに来てください☆
今後はVRchatへの移行も試みたいと画策中です。

https://cluster.mu/w/f7b1503b-0d7f-4290-bbb6-f95a8e0b60a0

アバターペデスタルというお着換え機能

VRChatにはワールドの中に入っている状態でも、
公開されているアバターに気軽に着替えることができます。


新しく連れて行ったエリンギにお着換え。


こんな感覚で持ち込んだ装飾品を気軽に身に付けたりできるようになると楽しそう♪
clusterでもできたらいいのにな、

玉ねぎやエリンギになりたい方、大歓迎です♪

エリンギ
玉ねぎ

プラットフォームを越えて楽しんでみる

先日VRChatに連れていった玉ねぎアバターを今度は日本製のソーシャルVRのclusterに連れていってみました♪

clusterで記念撮影


これまでのSNSではプラットフォームが変わっても誰かを特定してもらえるように同じアイコンを使いまわしたりしていましたが、今後メタバースが一般化していったら、きっと今のSNSのように生まれては淘汰されてと、様々なプラットフォームが登場してくると思うので、これまでのアイコンと同じ感覚で個人個人で持っているアバターや部屋をプラットフォームを越えていろんなところで利用するようになるのかもしれないですね。

とりあえずここまでに現実にあるものをベースにして3Dモデル化をおこなってみて、更にアバター化した上で、VRChatとclusterと複数のプラットフォームへアップロードして活動してみるというところまで実践してみました。

プラットフォームを越えたアバターアップロードに挑戦

複数のプラットフォームで利用しようとした時に今は手元でコピーしたものをアップロードしているので、いくらでも複製できてしまって一意性が保てないのですが、こういったところにブロックチェーンの技術が乗ってくると楽しくなりそうです♪まだ装飾品やアイテムなんかも独自のプラットフォームに閉じている段階かと思いますが、すぐにそんな時代がやってきそうです。

とはいえ私が実践したようなアバターやワールドの作成はまだまだ誰にでも出来るようなフェーズへは進んでいないと感じるので、もう少し時間はかかるのでしょうか。

まずは手軽に参加できて、楽しい時間を体感したり共有できたりすることができるコンテンツがどんどん増えていくと人も増えて技術も加速していくのかな、
VRChatに比べるとclusterの人口はまだ少なそうですが、スマホからも参加可能な手軽さが最初に始めるのには良いのかなと感じます☆

3Dモデリングからテクスチャリングにリギング

少しだけ3Dモデリングをかじって、
3Dアバターを作成してVRChatの世界へ連れて行ってみました♪

たまねぎ星人誕生

ネット上にはたくさんの情報が転がっているので、
ググりながらモデリングにテクスチャにリギングと、
先日フォトグラメトリ化したリアル玉ねぎをベースに、
blenderでごにょごにょと生成しました!!

blender作成画面

会話をすると音声を拾って音に合わせて
口の形も変わるように設定しています♪

これでVR世界でのアバターってものが少しだけ分かった気がします。

まだまだ個人で自由に好きなアバターを用意するのは簡単では無いかもしれないですが、
今後リッチなエディタがどんどん出てきそうですね。

プラットフォームを越えて
装飾品が自由にカスタマイズできるようになっていくと面白いです!

PS.
マイワールドには先日までの
キウイと玉ねぎとバナナに加えて
エリンギとジャガイモも持って行きました(笑)

見て、感じて、知ろう

3Dモデルを作成してアップロードしたり、
自分だけの空間を作ってみたり、
VR空間での活動も徐々に慣れてきたので、
実際にVRゴーグルをつけた時にはどう見えるのか、
どう感じ取れるのか、
これは体験しないと分からないと思い。
エントリーモデルとしてはちょうど良さそうな、
Meta Quest 2」を購入しました♪

Meta Quest 2(128GB)

一昔前にVRゴーグルをお試しでかけたことはありましたが、
その時は正直あまり実用性は感じられず、
「ふ~ん、こんな感じか、」で終わってしまいましたが、

時代は進んでいますね!!
先日作成したバナナと野菜の世界にも訪れてみましたが、
没入感をたっぷりと味わえました。

VRChatでは今やっとビジネスの中でも一般的になってきた、
チャットやWeb会議ツールでの文字やWebカメラなどによる
平面上でのコミュニケーションでは体感できない、
ジェスチャーなど立体的な表現や
距離感を活かしたコミュニケーションもとれ
表現の手段が一気に増えるように思えます。

VRChatキャプチャ

次な何にチャレンジしてみようかな。

VRChatID:TakafumiCreate