VRCでワールド制作においての固定砲台的なものの作成の仕方

概要

この記事は、以下のワールドで、作成した固定された筐体でハンドルを動かしたらそれに伴って、砲身も一緒に動くといった仕組みを作成する際の問題解決に関するものです。

作ったワールド

https://vrchat.com/home/launch?worldId=wrld_7c9e20ea-fb8c-4a1c-9cb8-ff17d560056b

この記事を読む事で、以下の内容を知る事ができます。 - 固定砲台系のハンドルと砲身の動かし方 - 一部同期の話

元としては、遊園地の車両に乗って、的を狙って点数を稼ぐアトラクションを模しています。

 開発環境

Unity2018.4.20f1 VRCSDK3-WORLD-2020.10.28 15.57_Public(なお作成時点ではすでに古い) U# v0.18.8 

固定砲台系とは?

ここでいう固定砲台系というものは以下の要件を満たすものです。 - ハンドルを持ったタイミングから砲身が、ハンドルの方角と逆方向に砲身が向いている。 - 他人から見たときに、ハンドルを持ったタイミングから動きだし、それ以外は動かない - さわっていない時は、初期位置に戻る

VRCのPickUpのみを利用した場合

おそらくもっとも最初に思いつく方法かなと思います。 色んなワールドで、PickUp使用して動かしている事があるので、もっとも身近で、最初に思いつくものじゃないかなと思います。 もちろん私も最初に試してみました。

結論を言ってしまうと、うまくいきませんでした。

理由はシンプルなもので、「固定砲台系とは?」の部分で書いた通り、それ単体だけでは解決出来るものではなかったためでした。

逆に、もの「単体」としての動作(例えば、銃を持つ、剣を持つ)の場合はかなり有効且つシンプルなもので、PickUpを追加するだけでとても楽に実装する事ができます。

実際に行ったアプローチ

そのため、基本的には今回は、以下のアプローチになりました。 1. PickUpObjectを持った時に、「操縦桿」を持ったという事を「銃身及びハンドルを動かす」部分に対して、通知を行う。この通知は、同期を行うため、そのオブジェクトのオーナーになった上で他の人にも送るようにする。 2. 通知が行われたら、「操縦桿」と「銃身」の中心となるオブジェクトの位置に対して、PickUpObjectの位置との差分を取って、それを操縦桿の方角、それと逆方向を銃身の方角に変更する。

---

f:id:herie270714:20210204183037p:plain
通知を行う図

同期に関しては、以下の記事にて、もう少し詳細を記述しているので、そちらをごらんください。

Udonのワールドを作った時の同期の話 - herie270714’s blog

さて、結局のところ、この仕組みとして肝となるものとしては 1. PickUpObjectとハンドルの動かす処理をしている所は違う 2. PickUpを行ったという通知を行う

の2点にかぎられています。 1に関しては、最初のPickUpのみを使用した際に発生する問題点の回避のために行うものです。PickUpObjectは常に同期されてしまうため、それによって、見かけのハンドルと、それ 2に関しては、時分以外の人の弾が飛んでいる場所を計算するために必要だったので同期を行っています。もう少しかみ砕くならば、2の通知が来ることで、受け取り手側の指定の操縦桿が動いている状態であるとなり、その人側で、送信者の手の動きに対しての位置から計算して、疑似的にほぼ同様の動きをさせています。

この時、同期されているのは、手の動き(PickUpOject)のみであり、それ以外は、同期されている内容に対して、「ローカル上」で再現を行っているというものです。

この「ローカル上」というのは、自分のPC上で動いている状態のものをさします。 この「ローカル上」では、通信によって、相手の状態が通信で、おくられてこないとそれらが再現されないものです。一番身近な例かはわかりませんが、通信状況が不安定な状態(相手の状態が送られてきていない状態)から、安定した際に、相手のポジションがワープする(最新の相手の状態が送られてくる)といったものが身近かもしれません。

なので、砲身などは同期を取らなければ、他人から見たときには、動かないものですから、PickUpを行ったというものを通知して、以降は、PickUpによる位置同期のみで「各ローカル上」で再現を行っています。

この同期を行う理由としては、主に相手の弾を撃った場所を特定するためです。 VRCでの同期、通信などは、値の同期はたしかに可能ですが、 以下の記事によると

Udon開発する上での注意点[Unity]

https://qiita.com/toRisouP/items/16bd06aa303a1bb1a747

UdonSyncは「常に送信している」ものであり、量によっては、大変負荷がかかるっていうものらしいのです。 一番実直に書くならば「位置」と、「向き」を同期すれば、可能だとはおもいますが、上記の仕組みをVRCPickUpと別に使用する必要が出てくるため、それらを少しでも控ようといった具合のためです。

また、本来の目的である、「他人がどこらへんを狙ったか?」によって、自分の弾と混在する遊園地のあのアトラクションのごちゃごちゃ感も「弾を打った」という同期だけで達成する事ができます。

弾の同期に関しても同様に、UdonSyncを使用して、直接的に位置の同期を行う事もできます。 しかし、砲身がシュミレートによって向いているであろう場所を向いているので、わざわざ位置同期をしなくても、「そのタイミング」「その方向」さえわかれば写真判定レベルの事をしないとわからないレベルでそれっぽく動いている事でしょう。

終わりに

今回は、「UdonSync」に絡むものを極力使わない方向性で作成しました。近いものとしては、今回のワールドにおいては、PickUpのみしかUdonSyncに近い動作のものがないのではないでしょうか? その関係で、他にもそれっぽく動かしているというものがあり、それらは長くなるので、以下の内容にまとめています。 どうぞお時間とご興味がありましたら、ご一読ください。