Skip to content

Multiuser

AmaneYamaguchi edited this page Oct 31, 2024 · 3 revisions

PoseSynthではUnity公式のマルチユーザパッケージ「Unity Netcode for GameObject(以下Netcode)」を使用してマルチユーザを実装しています. Netcodeではサーバ・クライアント方式またはホスト・クライアント方式によってマルチユーザを実現します. 具体的なマルチユーザの実装方法はバージョンにより異なりますのでご注意ください.

Netcode基礎

まず,PoseSynthのマルチユーザ実装の説明に必要なNetcodeの基礎について説明します. 詳細は公式ドキュメント等を参照してください.

NetworkManager

NetworkManager はサーバの作成やクライアントの参加等,マルチユーザ全般の管理を行うコンポーネントです.

NetworkObject

NetworkObject コンポーネントはマルチユーザに対応したゲームオブジェクトに対してアタッチします. サーバで NetworkObject.Spawn() を呼び出すことで各クライアントにそのゲームオブジェクト(及び子オブジェクト)が生成されます. NetworkObject.Despawn() を呼び出すことで削除されます.

NetworkTransform

NetworkTransform コンポーネントはマルチユーザに対応した Transform です. Transform の内容が全てのクライアントに同期されます.

NetworkBehaviour

NetworkBehaviour コンポーネントはマルチユーザに対応した MonoBehaviour です. MonoBehaviour と同様に継承して使用することで,サーバやクライアント別に異なる処理を行うスクリプトを記述できます.

なお,ローカルネットワーク内の複数のPC間で通信を行う場合,PCのファイアウォール設定でUnity Editorのローカルネットワーク通信を許可する必要があります.

v1.1.0以降のネットワーク構造

このバージョンでは以下の情報がサーバを通じて全クライアントに同期されます.

  • 各クライアントの LocalCameraRig に含まれる Transform

各クライアントのCameraRigの同期

クライアントはサーバに入ると,サーバがクライアントの LocalCameraRig と同様の階層構造を持つゲームオブジェクトを生成します. このゲームオブジェクトには NetworkObject がアタッチされているためNetcodeによるマルチユーザに対応しています. また,子オブジェクトには NetworkTransform (正確には継承して仕様に変更を加えた ClientNetworkTransform )がアタッチされており,各クライアントに Transform の情報が同期されます.

このゲームオブジェクトには ICameraRig インタフェースを継承したコンポーネント ServerCameraRig がアタッチされています. ServerCameraRig に含まれるゲームオブジェクトの Transform の情報は同じ TrackerType と対応付けられた LocalCameraRigTransform の情報が同期されます. アバタの動作を生成するクラス PoseMapper は, LocalCameraRig と同様に ServerCameraRig も動作生成のために参照できます. ServerCameraRig は自分自身を含むクライアントの数だけScene上に生成されます.

graph LR
VRPackage -->|位置・姿勢を代入| HMD
VRPackage -->|〃| LeftHand
VRPackage -->|〃| RightHand

HMD <-.->|bind| HeadIKTarget
LeftHand <-.->|bind| HandLeftIKTarget
RightHand <-.->|bind| HandRightIKTarget

HMD -->|同期| ServerHMD
LeftHand -->|同期| ServerLeftHand
RightHand -->|同期| ServerRightHand

ServerHMD <-.->|bind| ServerHeadIKTarget
ServerLeftHand <-.->|bind| ServerHandLeftIKTarget
ServerRightHand <-.->|bind| ServerHandRightIKTarget

ServerHeadIKTarget -->|Transformの位置を入力として参照| VRIKMapper
ServerHandLeftIKTarget -->|〃| VRIKMapper
ServerHandRightIKTarget -->|〃| VRIKMapper

VRPackage{{VR用パッケージ}}
subgraph LocalCameraRig
  HMD("HMD Transform")
  LeftHand("Left Hand Transform")
  RightHand("Right Hand Transform")
  HeadIKTarget("TrackerType.HeadIKTarget")
  HandLeftIKTarget("TrackerType.HandLeftIKTarget")
  HandRightIKTarget("TrackerType.HandRightIKTarget")
end
subgraph ServerCameraRig
  ServerHMD("HMD Transform")
  ServerLeftHand("Left Hand Transform")
  ServerRightHand("Right Hand Transform")
  ServerHeadIKTarget("TrackerType.HeadIKTarget")
  ServerHandLeftIKTarget("TrackerType.HandLeftIKTarget")
  ServerHandRightIKTarget("TrackerType.HandRightIKTarget")
end
VRIKMapper["アバタの動作生成用クラス"]
Loading

各クライアントによるアバタの動作生成

v1.0.1ではアバタの動作をサーバが生成した後,サーバがそのアバタの動作を各クライアントに同期していましたが,v1.1.0以降は通信する情報量の削減のため,融合アバタを含む各アバタの動作の生成は各クライアントが独立して行います. PoseMixer の重みの値等,各クライアントに同期したい情報は個別に同期を行います.

PoseMixer の値の同期

PoseMixer コンポーネントがアタッチされたアバタに追加で NetworkPoseMixer コンポーネントをアタッチすると, PoseMixer の重みの値が各クライアントに同期されるようになります.

v1.0.1のネットワーク構造

このバージョンでは以下の情報がサーバを通じて全クライアントに同期されます.

  • 各クライアントの LocalCameraRig に含まれる Transform
  • NetworkPose コンポーネントがアタッチされたアバタの Pose の情報

各クライアントのCameraRigの同期

クライアントはサーバに入ると,サーバがクライアントの LocalCameraRig と同様の階層構造を持つゲームオブジェクトを生成します. このゲームオブジェクトには NetworkObject がアタッチされているためNetcodeによるマルチユーザに対応しています. また,子オブジェクトには NetworkTransform (正確には継承して仕様に変更を加えた ClientNetworkTransform )がアタッチされており,各クライアントに Transform の情報が同期されます.

このゲームオブジェクトには ICameraRig インタフェースを継承したコンポーネント ServerCameraRig がアタッチされています. ServerCameraRig に含まれるゲームオブジェクトの Transform の情報は同じ TrackerType と対応付けられた LocalCameraRigTransform の情報が同期されます. アバタの動作を生成するクラス PoseMapper は, LocalCameraRig と同様に ServerCameraRig も動作生成のために参照できます. ServerCameraRig は自分自身を含むクライアントの数だけScene上に生成されます.

graph LR
VRPackage -->|位置・姿勢を代入| HMD
VRPackage -->|〃| LeftHand
VRPackage -->|〃| RightHand

HMD <-.->|bind| HeadIKTarget
LeftHand <-.->|bind| HandLeftIKTarget
RightHand <-.->|bind| HandRightIKTarget

HMD -->|同期| ServerHMD
LeftHand -->|同期| ServerLeftHand
RightHand -->|同期| ServerRightHand

ServerHMD <-.->|bind| ServerHeadIKTarget
ServerLeftHand <-.->|bind| ServerHandLeftIKTarget
ServerRightHand <-.->|bind| ServerHandRightIKTarget

ServerHeadIKTarget -->|Transformの位置を入力として参照| VRIKMapper
ServerHandLeftIKTarget -->|〃| VRIKMapper
ServerHandRightIKTarget -->|〃| VRIKMapper

VRPackage{{VR用パッケージ}}
subgraph LocalCameraRig
  HMD("HMD Transform")
  LeftHand("Left Hand Transform")
  RightHand("Right Hand Transform")
  HeadIKTarget("TrackerType.HeadIKTarget")
  HandLeftIKTarget("TrackerType.HandLeftIKTarget")
  HandRightIKTarget("TrackerType.HandRightIKTarget")
end
subgraph ServerCameraRig
  ServerHMD("HMD Transform")
  ServerLeftHand("Left Hand Transform")
  ServerRightHand("Right Hand Transform")
  ServerHeadIKTarget("TrackerType.HeadIKTarget")
  ServerHandLeftIKTarget("TrackerType.HandLeftIKTarget")
  ServerHandRightIKTarget("TrackerType.HandRightIKTarget")
end
VRIKMapper["アバタの動作生成用クラス"]
Loading

アバタの動作の同期

融合アバタを含むアバタの動作の生成はサーバが行います. クライアントに同期したいアバタに対しては, NetworkPose コンポーネントをアタッチします. すると,そのアバタの動作が各クライアントに同期されます.

Clone this wiki locally