😺
Unity Multiplayer Networkingを使ってみる
UnityでオンラインマルチプレイといえばPhotonが有名ですが、Unity自体も同様のサービスを提供しています。
どちらも無料で使うことができますが、PhotonFusionのFREE100CCUプランは1カスタマー1アプリまでの制限があります。また20CCUプランは開発のみにしか使えません。
それに対してUnity Gaming ServiceのRelayは50CCUまで無料となっていますので、無料で利用する分にはPhotonFusionより有利です。
そう思ってUnity Multiplayer Networkingを試してみたのですが、Photonに比べるとけっこう面倒なことが多いので、備忘録としてまとめておきます。
使用バージョン
- Unity 2022.3.24f1
- Lobby 1.1.2
- Relay 1.0.5
- Netcode for GameObjects 1.8.1
概要
Photonは1つにほぼまとまっていますが、Unity Multiplayer NetworkingではLobby/Relay/Netcodeに分かれています。これら3つを合わせたものがだいたいPhotonと同等になるかと思います。
分かれているせいでかなりわかりずらいですが、おそらく一般的には
- Lobbyでマッチング
- Relayを使ってゲーム同士をネットワーク接続
- Netcodeを使って同期プレイを実装
のような流れになるかと思われます。
それぞれの使い方については公式にサンプルやドキュメント、またネット上にも試している方がいるのでここでは書きません。
以下には自分が試していてハマったことを記述しておきます。
Lobby
- アプリを終了してもロビーに残る
- とりあえずDashboardのLobbyの設定で、
Disconnect Removal Time
を最小(10s)に設定しておく -
Application.wantToQuit
などでILobbyService.RemovePlayerAsync
を呼ぶと良い -
OnDisable
やOnDestroy
でILobbyService.RemovePlayerAsync
を呼んでもダメ-
Task.Result
でブロックすると固まるのでさらにダメ
-
- とりあえずDashboardのLobbyの設定で、
-
LobbyEventCallbacks
の設定が面倒-
LobbyChanged
でほぼすべて受け取ることがでるので、これだけで十分 -
LobbyChanged
のコールバックの中でILobbyChanges.ApplyToLobby
を呼ぶと変更を反映できる
-
-
LobbyEventCallbacks.LobbyChanged
でPlayerJoined
を検出したタイミングで、UpdateLobbyAsync
でロビーデータを更新するとJoinしたプレイヤーに伝わらない-
UpdateLobbyAsync
の前にTask.Delay(1000)
を入れると伝わる
-
- 基本的にプレイヤーはPlayerIdで扱われるが、一部のコールバック(
PlayerLeft
やPlayerData.Changed
など)ではPlayerIndexが使用される- PlayerIndexは固定ではなく、誰かがLeaveしたりすると振り直される
Netcode
- クライアントからネットワークオブジェクトを生成できない
- ネットワークオブジェクトを生成できるのはホストのみです
- RPCを使ってホストに生成を依頼する必要があります
- Netcode-2.0ではdistributed authorityによりクライアントからも生成できるになるかも
- クライアントがOwnerなのに動かせない
-
NetworkTransform
のOnIsServerAuthoritative
が常に真を返すせいです -
NetworkTransform
を継承したクラスを作成し、OnIsServerAuthoritative
でfalse
を返すようにしたコンポーネントを使用します
-
Discussion