😺
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