こんにちは、ちゃらいプログラマです。
前回の続きでLobby/Relayへの接続周りを説明していきます。
※前回の記事はこちら
Unity Lobby/Relay入門 (#1) - アヒルのある日
処理の流れ
ホスト、クライアントで若干異なります。
MultiGameManagerクラスを作成して処理を作成します。
接続
// 認証済判定 private bool m_isAuthentication = false; // 認証ID private string m_authenticationId = string.Empty; // 接続 public async UniTask ConnectAsync() { if(!m_isAuthentication) { // "ユーザ識別ID"はアプリ毎に適切なIDを設定してください var option = new InitializationOptions(); option.SetProfile( "ユーザ識別ID" ); await UnityServices.InitializeAsync( option ); await AuthenticationService.Instance.SignInAnonymouslyAsync(); // 上記で渡す"ユーザ識別ID"がゲーム起動時から変わらないのであれば // 本処理は一度のみで問題ありません m_isAuthentication = true; // 参照時の処理負荷が激しいのでキャッシュしておきます m_authenticationId = AuthenticationService.Instance.PlayerId; // コールバック登録 Unity.Netcode.NetworkManager.Singleton.OnServerStarted += OnServerStarted; Unity.Netcode.NetworkManager.Singleton.OnServerStopped+= OnServerStopped; Unity.Netcode.NetworkManager.Singleton.OnClientStarted+= OnClientStarted; Unity.Netcode.NetworkManager.Singleton.OnClientStopped+= OnClientStopped; Unity.Netcode.NetworkManager.Singleton.OnTransportFailure+= OnTransportFailure; } } // ホスト起動コールバック private void OnServerStarted() { // ホストモードでゲーム開始した際に呼び出されます } // ホスト停止コールバック private void OnServerStopped(bool isStop) { // ホストモードで接続が解除された際に呼び出されます } // クライアント起動コールバック private void OnClientStarted() { // クライアントモードでゲーム開始した際に呼び出されます // ホストモードでゲーム開始した際にも呼び出されます } // クライアント停止コールバック private void OnClientStopped( bool isStop ) { // クライアントモードで接続が解除された際に呼び出されます } // 切断コールバック private void OnTransportFailure() { // ネットワークが切断された際に呼び出されます }
ホスト側
- 接続
- Relayネットワークを生成
private async UniTask<string> CreateRelayAsync( int connectionNumMax ) { // 接続最大数を渡してネットワークを生成します var allocation = await RelayService.Instance.CreateAllocationAsync( connectionNumMax ); // 接続用のIDを取得しておきます string roomId = await RelayService.Instance.GetJoinCodeAsync( allocation.AllocationId ); // 接続フォーマットを設定します var serverData = new RelayServerData( allocation, "dtls" ); var transport = Unity.Netcode.NetworkManager.Singleton.GetComponent<UnityTransport>(); transport.SetRelayServerData( serverData ); return roomId; }
- Lobbyを生成
// 接続ロビー情報 private Lobby m_lobby = null; // ロビー生成 private async UniTask<Lobby> CreateLobbyAsync( string lobbyName, string roomId, int connectionNumMax ) { // 接続用のIDを生成時のオプションに設定します // アプリ毎に設定数は異なります(最小設定だと以下のようになります) var options = new CreateLobbyOptions(); options.Data = new() { // フォーマットは // "任意の文字列", "DataObject型" { "RoomID", new DataObject( visibility: DataObject.VisibilityOptions.Public, value: roomId }, }; // ロビー生成 m_lobby = await LobbyService.Instance.CreateLobbyAsync( lobbyName, connectionNumMax, options ); }
- ホストモードでゲーム開始
Unity.Netcode.NetworkManager.Singleton.StartHost();
- 一定時間毎にLobbyへHeartBeat送信
// ロビー接続ポーリングコルーチン private Coroutine m_lobbyCoroutine = null; // ロビー接続継続開始 private void StartLobbyHeartbeat() { StopLobbyHeartbeat(); m_lobbyCoroutine = StartCoroutine( LobbyHeartbeatCoroutine() ); } // ロビー接続継続停止 private void StopLobbyHeartbeat() { if (m_lobbyCoroutine != null) { StopCoroutine( m_lobbyCoroutine ); m_lobbyCoroutine = null; } } // ロビー接続ポーリング private IEnumerator LobbyHeartbeatCoroutine() { var delay = new WaitForSeconds( 15 ); while (true) { LobbyService.Instance.SendHeartbeatPingAsync( m_lobby.Id ); yield return delay; } }
- 切断(任意のタイミングで)
クライアント側
- 接続
- Lobbyリスト取得と参加
private async UniTask<string> JoinLobbyAsync() { // 空いているロビーへ接続します var queryLobbyOptions = new QueryLobbiesOptions(); queryLobbyOptions.Count = 20; // 検索数 queryLobbyOptions.Order= new() { new QueryOrder( asc: false, field: QueryOrder.FieldOptions.Created ), }; var lobbies = await Lobbies.Instance.QueryLobbiesAsync( queryLobbyOptions ); string lobbyId = string.Empty; string roomId = string.Empty; foreach (var result in lobbies.Results) { lobbyId = result.Id; // CreateLobbyAsync()にてオプションに設定した // "RoomID"を参照して接続用IDを取得します roomId = result.Data["RoomID"].Value; break; } // ロビー参加 if(lobbyId != "") { m_lobby = await LobbyService.Instance.JoinLobbyByIdAsync( lobbyId ); } return roomId; }
- Relayネットワークへ接続
private async UniTask JoinRelayAsync( string roomId ) { // 接続用のIDを元にネットワークへ接続します var allocation = await RelayService.Instance.JoinAllocationAsync( roomId ); // 接続フォーマットを設定します var serverData = new RelayServerData( allocation, "dtls" ); var transport = Unity.Netcode.NetworkManager.Singleton.GetComponent<UnityTransport>(); transport.SetRelayServerData( serverData ); }
- クライアントモードでゲーム開始
Unity.Netcode.NetworkManager.Singleton.StartClient();
- 切断(任意のタイミングで)
切断
// 切断 public async UniTask DisconnectAsync() { if(m_isAuthentication) { // ロビー接続継続停止 StopLobbyHeartbeat(); // ロビーから抜ける await LobbyService.Instance.RemovePlayerAsync( m_lobby.Id, m_authenticationId ); m_lobby = null; // Relay接続解除 Unity.Netcode.NetworkManager.Singleton?.Shutdown(); } }
駆け足で説明しましたが、上記でホスト端末へ接続できるようになります。
次回はRPC周りの説明ができればと… また次回。