同期関連
オブジェクトの同期に関する情報のまとめ。
同期について理解する第一歩
同期方法簡易まとめ
とりあえず簡単に同期方法だけ知りたい人向け。
オーナーシップは適時取得する事。
同期方法簡易まとめ
オーナーシップ
- オブジェクト一つ一つに設定されており、同期の際、オーナーシップを所有しているプレイヤーを基準にして各オブジェクトの同期が行われる。
- ワールドに配置されたオブジェクトのオーナーシップは、最初はワールドのMasterに設定されている。
オーナーシップを持ったプレイヤーが退出した場合、オーナーシップはMasterに戻る。
- オブジェクトのオーナーシップを変更する方法は、以下が確認されている。
- VRC_Pickup
オブジェクトをPickupしたプレイヤーが、そのオブジェクトのオーナーシップを取得する。 - Station
VRC_Pickupを追加したStationに座ったプレイヤーがそのオブジェクトのオーナーシップを取得する。 - オブジェクト同士の物理的接触
VRC_ObjectSyncを持ち、AllowCollisionTransfarがTrueのオブジェクト同士が、
Rigidbodyによる物理的接触をした際、オーナーシップがコピーされる。 - TakeOwnership
SendRPCアクションを通して、VRC_ObjectSyncとVRC_Pickupを持つオブジェクトの
TakeOwnership関数を実行することで、実行したプレイヤーがオーナーシップを取得する。 - SpawnObject
Spawnしたオブジェクトのオーナーシップは、SpawnObjectアクションを実行したプレイヤーが取得する。
- 子を持つオブジェクトのオーナーシップを取得した場合、そのオブジェクトの全ての子孫のオーナーシップを同時に取得する。
ただし、親子内にObjectSyncが複数存在する場合は例外となる。- VRC_ObjectSyncを入れ子にした際のオーナーシップの検証
https://twitter.com/hatsuca_vr/status/995603275645779969
- VRC_ObjectSyncを入れ子にした際のオーナーシップの検証
同期
- オブジェクトにVRC_ObjectSyncを加える事で、オーナーシップを所有しているプレイヤー(以下オーナー)のPC上でのオブジェクトの状態を基準にして、他のプレイヤー(以下クライアント)のPC上の同オブジェクトのTransformやアニメーションを同期する事ができる。
- オーナー上でのオブジェクトのTransformは各クライアントにキャッシュされ、毎フレームのFixedUpdateで同期されていると思われる。そのため、その後にクライアント側でTransformの変化が生じた場合、同期が正常に行われていないように見える場合がある。
- アニメーションの同期は再生開始時と、再生位置(再生時間)が変更される度に行われる。そのため再生速度が0の場合、新たな同期は行われない。
- VRC_ObjectSyncによる同期は以下の3パターンに分けられる。
- 物理、スクリプトによる同期
物理演算やスクリプトによってTransformが変化した際の同期。 - 親子関係による同期
親を持つオブジェクトを同期するとき、
親のTransformの変化によって子のWorld上のTransformが変化した際の同期。
この同期を機能させるにはオブジェクトにVRC_Pickupが追加されている必要がある。 - アニメーションの同期
オブジェクト上でTransformの変化を含むアニメーションが再生された際の同期。
RootMotionがFalseのアニメーションを同期する場合、アニメーションを再生するオブジェクトにVRC_ObjectSync、
そのアニメーションによってTransformが変化するオブジェクトにVRC_ObjectSyncとVRC_Pickupが追加されている必要がある。
RootMotionがTrueのアニメーションはVRC_ObjectSyncのみで同期できるが、Avatarが設定されていない場合は正常に同期しない。
また、VRC_SyncAnimationを使うことでVRC_ObjectSyncやVRC_Pickup無しでもアニメーションを同期することができる。こちらの場合はTransformの変化を含まないアニメーションでも同期する事ができる。
VRCSDK3UDONに向けての同期の話
記載者:Satetu 2020/4/9/
UDONの同期に苦しめられる人間が結構いると思うので同期についての話をします
1.なぜ動機がバグるか?
Unityの同期の上にUDONの同期が乗っかっているため、UDONが「これ同期して」って言ってもUnity側が「こちらの設計上それは出来ません」と突っぱねる事があるからだ。なのでまずUnityの同期について知る必要がある
2.Unityの同期
・Unityの同期システムはこうだ。Serverがある。Serverが全権を握っている。そしてプレイヤー側はLocalだ。セキュリティの関係上LocalはServerに対して何もできない。
・それだとゲームが成立しないのでプレイヤーは所有しているオブジェクトから限られた範囲でサーバーに関与できる。オブジェクトの所有権限を「Authority」と呼ぶ。Authorityを持つオブジェクトがサーバーに関与する方法が「Sync」
・UnityはデフォルトでプレイヤーキャラオブジェクトのAuthorityをプレイヤー側に渡している。これによってプレイヤーはAuthorityを持つ自分のキャラを操作し、その操作がSyncでサーバー側と同期され、その後サーバーと他のプレイヤーが同期するという仕組み
・オブジェクトの「Authority」がサーバーにあるなら「Sync」はサーバーと同じ値になる。一方でプレイヤーが「Authority」を保持しているなら「Sync」はプレイヤーと同じ値になる。
・当たり前だがLocalがLocalにAuthorityを与える事は出来ない。そんな事が出来たらセキュリティも何もあったもんじゃないからな。Authorityの変更はServerにしか出来ない
・基本的に全てのオブジェクトのAuthorityはServerが持っているが、VRChatはそうではないので注意。
UDONの同期
・恐らくVRChatのプレイヤーは全てLocalでありServerは存在しない。MasterもOwnerもLocal
・VRChatにはServerが存在する。ただしUDONからは関与不能(そもそもVRCSDKやUDONはサーバーを悪意あるプログラムから保護するために開発されたので関与できないのは当然と言える)
・MasterとはServerから全てのオブジェクトのAuthorityを与えられたLocalである。そしてMasterが部屋から居なくなるとServerがMasterが所有していたオブジェクトの権限を次のプレイヤーに委譲する。椅子に座ってるMasterが退出すると他のプレイヤーが椅子に吸い込まれるバグは恐らくこれが原因
・Masterは「Authorityを与えらたLocal」なのでServerのように他のプレイヤーからAuthorityを取り上げたり、直接干渉することができない。このためMasterをServerのように使うと失敗する。Masterが関与できるのはあくまで「他のプレイヤーがAuthorityを獲得していないオブジェクト」のみ
・これがどのように影響するかと言うと「Masterが散らばった物を一括で片付けることは出来ない」あたり。例えばカードゲームのカードはPickupした時点でAuthorityが他のLocalに移るので、Masterはそれを操作する権限を失い操作できなくなる。これが回収ボタンを押してもなお空中に残るカードの仕組み
・場合によってSetOwnerが機能しないのは「LocalはLocalにAuthorityを付与できない」というUnity側のルールに抵触しているからだ。ServerだけがAuthorityの操作が出来る。Udonのアクションの中にはServerを通してAuthorityの変更を行ってくれるものが幾つかあり、それを正しく使用した時のみAuthorityを移す事ができる
総括
・このように、VRChatのワールド開発は「Serverはあるがセキュリティの関係上触らせてもらえない状態」でやる事になるため「一括で移動」とか「一括で〇〇」みたいな仕組みは実現しにくい。一括移動なら「狭い部屋に入れて絶対避けられない当たり判定を下から押し付ける」みたいな工夫が必要になる
・リトルビッグプラネット・マリオメーカー・Minecraftのダンジョンマップなどの、Serverを触れないゲーム制作にこの手の工夫がいっぱいあるので参考にしてみるといいかも
その他参考資料
- https://qiita.com/hatsuca_vr/items/63ee6ba04d2a785eed16
同期のコツ - https://twitter.com/hatsuca_vr/status/1030117231286341632
PhotonViewが割り当てられるコンポーネント - http://edom18.hateblo.jp/entry/2017/03/01/090602
Photon(Unityアプリケーションの通信方法の1つ)
コメント・情報提供
- 最終更新:2020-04-09 16:23:25