概要
前回 Unity Netcode を利用してThirdPersonサンプルをローカルネットワーク同期することに成功しました
今回はUnity Gaming ServicesのLobby / Relayを使って
NAT超えでのネットワーク同期を行います
Unity Gaming Servicesとは
ゲーム開発に必要な機能がパッケージ化され提供されています
今回は以下の3点を使います
・マルチプレイヤーフレームワークであるNetcode
・ゲームロビーを作成できるLobby
・P2Pネットワークでプレイヤー同士を繋ぐRelay
Multiplayerの使用には支払い情報が必要です
少人数開発中は支払いが発生するケースは少ないですが
大人数になると発生する可能性があるので注意です
下記までは無料です
Lobby : 10 GiB / month per regional group: US + EU and Asia + Australia
Relay : First 50 CCU for free / month
NAT超えとは
通信に必要なIPアドレスには世界中から自宅や会社を特定するグローバルIPアドレスと
自宅や会社内で端末ごとに振られるプライベートIPアドレスがあります
自宅や会社のルーター内では端末からグローバルネットに通信する際、プライベートIPアドレスをグローバルIPアドレスに変換しています(Network Address Translation、通称NAT)
これは内から外に通信する分には便利なのですが、外から内に通信するにはプライベートIPアドレスがわからず通信できません
オンラインゲームではグローバルネットから自宅・会社内の端末に通信する必要があるため
NAT超えの方法が重要となります
環境
Unity : 2022.1.14f1
Lobby : 1.0.3
Relay : 1.0.4
Netcode for GameObjects : 1.0.2
フロー
Project作成
まずUnity Gaming Services上でプロジェクトを作ります
UnityID > プロジェクト管理 > SignIn > Unity Gaming Services
Projects > Create Projects
プロジェクト名と対象年齢を入れてCreate Project
Unity Gaming ServicesとProjectの設定
プロジェクトの設定でLobbyとRelayを利用可能にします
UnityID > プロジェクト管理 > SignIn > Unity Gaming Services
Multiplayer > 画面上部から対象プロジェクトを選択
Get Started > Continue setup > 支払い情報を登録 > Complete
「Set up Multiplay」が表示されますが、今回はGame Server Hostingを使わないのでスルーします
左メニューのRelay > Setup Relayを押すとRelayのセットアップが始まります
同じ要領でLobbyもセットアップしておきます
Lobby/Relay用意フローと該当コード
- Lobbyのオーナーフロー
- Auth認証
UnityServices.InitializeAsync();
AuthenticationService.Instance.SignInAnonymouslyAsync();
- Relay鯖にAllocation ※1
RelayService.Instance.CreateAllocationAsync(maxConnections);
- Relay鯖へのJoinCode取得
RelayService.Instance.GetJoinCodeAsync(hostAllocationId);
- Lobby作成
Lobbies.Instance.CreateLobbyAsync(lobbyName, maxPlayers, createOptions);
- allocationからリレー鯖情報を取得してNetworkManagerに設定
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData);
- Hostとしてゲーム開始 ※2
NetworkManager.Singleton.StartHost();
- 一定時間ごとにLobbyにHeartBeat ※3
Lobbies.Instance.SendHeartbeatPingAsync(lobbyId);
- Auth認証
- Lobbyのゲストフロー
- Auth認証
UnityServices.InitializeAsync();
AuthenticationService.Instance.SignInAnonymouslyAsync();
- Lobbyリスト取得
Lobbies.Instance.QueryLobbiesAsync();
- Lobby参加
Lobbies.Instance.JoinLobbyByIdAsync(lobbyId, joinOptions);
- JoinCodeでRelay鯖に参加
RelayService.Instance.JoinAllocationAsync(joinCode);
- allocationから鯖情報を取得してNetworkManagerに設定 ※4
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData, allocation.HostConnectionData);
- Clientとしてゲームに参加
NetworkManager.Singleton.StartClient();
- Auth認証
※1 LobbyサンプルではLobby鯖を先に用意してからRelay鯖を用意してますが、JoinCodeを登録するのが手間だったのでRelayを先に行いました
※2 Dedicatedサーバーでも要点は同じはず
※3 HeartBeatを定期的に打たないとLobbyが自動終了します
※4 NetworkManagerへの登録はLobbyサンプルから変わってるので注意。多分あってるはず...
感想
かなり簡単にロビー機能とNAT超えを実装することができました
Lobbyの検索フィルタや入室コード、ランダム入室にも対応しており便利そうです
参考資料
- Lobby/Relayの最小規模サンプル
- Netcodeへのつなぎこみはやってくれないので注意
- Netcodeサンプルの一つ
- Relay周りが最新版と少し違う