🌟

Unityで手軽にP2P通信を実現!WebRTCベースのMistNetライブラリ紹介

2024/08/20に公開

概要

P2P通信とは、Peer to Peer通信の略で、端末同士が直接通信を行うことを指す。

MistNetは、開発者がP2P通信をより手軽に扱えるようにすることを目的として開発した。
Unityでの使用を想定している。
WebRTCをベースにしており、GameObjectの位置、Animation、RPC、変数の同期などを可能とする。

WebRTCについて

WebRTCではP2P型またはSelective Forwarding Unit (SFU) で利用されることが多い。
SFUはサーバーを経由する方式であり、音声や映像をサーバーを経由することで多くのユーザーに配信することができる。

本ライブラリは、P2P型の通信を行う。
WebRTCをUnityで利用できるパッケージが公開されていたため、こちらを利用することにした。
https://docs.unity3d.com/ja/Packages/com.unity.webrtc@3.0/manual/index.html

P2P通信を行うには、NAT越えの技術が必要。
これは、STUN/TURNサーバーを使用して、プライベートIPアドレスを持つデバイスが直接通信を行えるようにする。

Network Address Translation (NAT)とは、プライベートIPアドレスをグローバルIPアドレスに変換することを指す。

STUNサーバーによって、自身がサーバーに接続した際のグローバルIPアドレスとポート番号を知ることができる。
TURNサーバーは、直接通信ができない場合に、通信を中継するサーバーである。

接続方式の情報を交換するために、Signalingを行う。
Signalingとは、P2P通信を確立するために必要な情報交換を行うプロセス。
具体的には、WebRTCのOffer、Answer、Candidateをやり取りすることで、直接通信が可能になる。

これを行うために、Signalingのプログラムの作成を行った。
内容としては単純で、WebRTCにおける、Offer、Answer、Candidateを交換するだけである。
誰かのOfferが自身に来た場合、そのOfferを基にしたAnswerを返す。
その間にCandidateを交換する。

https://github.com/DecentralizedMetaverse/mistnet/blob/develop/MistNet/signaling_server.py

https://github.com/DecentralizedMetaverse/mistnet/blob/develop/Assets/MistNet/Runtime/Scripts/Core/MistSignalingServer.cs

MistNetの処理の流れ

まずは管理するObjectにIDを付与し、権限の設定を行う。
権限とは誰がそのObjectのOwnerであるかである。
次に、座標やアニメーションの同期、RPCを用いたイベント実行を通じて、ゲーム内の状態をリアルタイムに他のユーザーに反映させる。

Objectを生成する

  • 管理する際のIDを付与

Objectの権限の設定

  • 所有権、操作権限

Objectの同期

  • 座標
  • アニメーション

Objectの状態やイベント実行

  • 変数の同期
  • Remote Procedure Call (RPC)

作成したライブラリのプログラム例

状態が変化したとき

例えば、ゲーム内でプレイヤーのHPが減少した際、その状態を他のプレイヤーにも反映させるために、以下のように記述する。

[MistSync]
int hp { get; set; }

hpを直接変更すると、他のユーザーにも自動的に通知される。

記述方法については、既存のネットワークライブラリを参考にしている。

RPC

登録方法

[MistRpc]をメソッドの前につけます。

[MistRpc]
void RPC_○○ () {}

呼び出し方法

[SerializeField] MistSyncObject syncObject;

// 自身を含めた全員に送信する方法
syncObject.RPCAll(nameof(RPC_○○), args);

// 接続しているPeer全員に送信する方法
syncObject.RPCOther(nameof(RPC_○○), args);

// 送信先のIDを指定して実行する方法
syncObject.RPC(id, nameof(RPC_○○), args);

変数の同期

[MistSync]をつけることで、変数の同期が可能。

[MistSync]
int hp { get; set; }

同期のタイミングは、ユーザーが新しく参加した時と、値が変更時に自動的に行われます。

また、同期時に、任意のメソッドを実行することも可能。

[MistSync(OnChanged = nameof(OnChanged))]
int hp { get; set; }
void OnChanged();    

MistNet

MistNetはまだ開発初期段階であり、バグや改善の余地があるかもしれない。
Issueの報告やPull Requestを歓迎する。

https://github.com/DecentralizedMetaverse/mistnet

Discussion