LoginSignup
1
2

【Unity】Unityのオンライン関係の機能についてざっくりまとめてみる

Last updated at Posted at 2023-12-16

■ はじめに

オンラインゲーム作りたいなーと思ったので、個人的にまとめてみたいと思います。
(UGSは機能が豊富なので、やる気があれば当記事を随時更新します。)


■ UGSについて

  • Unity Gaming Services(UGS):Unityが提供する便利なツール群のこと。
    • ネットワーク関係の機能や、マッチング機能、ボイスチャット機能などのオンライン用のツール群
    • ゲームのパフォーマンス管理、プレイヤーの行動とかを記録する機能もあるっぽい
    • まだベータ版の機能が多い

● 料金


■ 機能一覧

● Netcode

  • 接続、同期などの機能を簡単に扱える
  • ローカルマルチプレイは、最低これだけでも実装可能

使用例

こんな感じに同期できます
Test.gif

  • ゲームの開始はこんな感じのメソッドを使う
    ゲームに参加.cs
    NetworkManager.Singleton.StartServer();      // サーバーとして接続開始
    NetworkManager.Singleton.StartHost();        // ホストとして接続開始
    NetworkManager.Singleton.StartClient();      // クライアントとして接続開始
    

  • NetworkObjectコンポーネントをつけると、オブジェクトの生成や破棄などを同期できる
    image.png
  • NetworkTransformコンポーネントをつけると、位置の同期ができる

  • NetworkBehaviourクラスを継承したスクリプトをNetworkObjectコンポーネントがアタッチされたオブジェクトにアタッチすると、RPCネットワーク変数などを利用できる
RPCとかについて.cs
[ClientRpc]
private void DoSomethingClientRpc(int randomInteger, ClientRpcParams clientRpcParams = default)
{
    if (IsOwner) return;

    // Run your client-side logic here!!
    Debug.LogFormat("GameObject: {0} has received a randomInteger with value: {1}", gameObject.name, randomInteger);
}

🔗参考リンク集

● Transport

  • ネットワーク系の処理のSDK

  • UDP, WebSocketを利用している

  • マルチプラットフォーム対応可能

  • TransportコンポーネントでRelayを指定すると、簡単にオンライン機能を使えるようになる
    image.png

  • 手動でも細かく設定してサーバーに接続したりできるぽい

● Authentication

  • プレイヤーの認証系の機能を使える
  • RelayやLobbyなどの機能を使う際に必須

使い道

  • オンラインゲームでのプレイヤーの情報の保存など
  • マルチプラットフォームでの連携サービスによるデータの同期

サインイン

  • 匿名認証:他の連携サービスを利用せずに匿名でゲームにサインインする
    • ソシャゲなどの「ゲストでログイン」的な感じ
  • サードパーティー認証:GooglePlayやApple Game Center、SteamなどのサードパーティーのIDプロバイダを利用してゲームにサインインする

使用例

  • 小規模なゲームで、マルチプラットフォームを考えてなければ、基本的に匿名認証でいい

    匿名認証.cs
    async void Awake()
    {
        // サービス初期化
        await UnityServices.InitializeAsync();
    
        // サインイン時にログ表示
        AuthenticationService.Instance.SignedIn += () => {
            print("Sined in:" + AuthenticationService.Instance.PlayerId);
        };
    
        // サインイン
        await AuthenticationService.Instance.SignInAnonymouslyAsync();
    }
    
  • サードパーティー認証

    • Project Settings/AuthenticationでIDプロバイダを設定する
      image.png

    • コード:(随時更新予定)

🔗参考リンク集

● Relay

  • Unityが提供するサーバーサービス
  • Relay Server、Relay Allocationという機能がある
    • Server:サーバー系の操作
    • Allocation:サーバーに対してプレイヤー用の空きスロットを予約する感じの操作をする
  • Steamworksなどの別のサーバーサービスを利用する場合、Relayは使わなくていいぽい

使用例

RelayManager.cs
/* Fields */
[SerializeField] int allocationCount = 1;

//-------------------------------------------------------------------
/* Methods */
public async Task<string> CreateRelay()
{
    try {
        // 割り当て作成
        var allocation = await RelayService.Instance.CreateAllocationAsync(allocationCount);

        // サーバーデータ設定
        var relayServerData = new RelayServerData(allocation, "dtls");
        var transport = Unity.Netcode.NetworkManager.Singleton.GetComponent<UnityTransport>();
        transport.SetRelayServerData(relayServerData);

        // 参加コードの取得
        var joinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);

        // ホストとして開始
        Unity.Netcode.NetworkManager.Singleton.StartHost();

        print($"サーバーを作成しました({allocation.AllocationId})");
        return joinCode;
    }
    catch (RelayServiceException e) {
        Debug.LogException(e);
        throw e;
    }
}

public async Task JoinRelay(string joinCode)
{
    try {
        // コードをもとに参加
        var joinedAllocation = await RelayService.Instance.JoinAllocationAsync(joinCode);

        // サーバーデータ設定
        RelayServerData serverData = new RelayServerData(joinedAllocation, "dtls");
        Unity.Netcode.NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(serverData);

        // クライアントとして開始
        Unity.Netcode.NetworkManager.Singleton.StartClient();
        print($"サーバーに参加しました({joinedAllocation.AllocationId})");
    }
    catch (RelayServiceException e) {
        Debug.LogException(e);
        throw e;
    }
}

🔗参考リンク集

● Lobby

  • ロビー(部屋)を作成して、他のプレイヤーとマッチングする機能
  • フレンド間でロビーコードを共有して参加できる、いわゆるプライベートマッチなども再現できる
  • ロビーの検索機能も充実していて、フィルター機能や並び替え機能もある

使用例

ロビー作成.cs
/// <summary> ロビー作成 </summary>
public async Task<Lobby> CreateLobby(string relayJoinCode)
{
    string lobbyNameID = Random.Range(1, 10000).ToString("D4");
    string lobbyName = "Lobby" + lobbyNameID;

    // ロビー設定
    CreateLobbyOptions options = new CreateLobbyOptions {
        // Relayの参加コードをロビーのデータに登録する
        Data = new Dictionary<string, DataObject> {
            {LOBBYS_JOIN_CODE_KEY, new DataObject(DataObject.VisibilityOptions.Member, relayJoinCode ,DataObject.IndexOptions.S1) },
        },
    };

    try {
        // まだ削除されていない場合、
        await UniTask.WaitWhile(() => isCreated, cancellationToken: destroyCancellationToken);

        // ロビー作成
        var lobby = await LobbyService.Instance.CreateLobbyAsync(lobbyName, 2, options);

        // イベント追加
        await LobbyService.Instance.SubscribeToLobbyEventsAsync(lobby.Id, EventCallbacks);

        print($"ロビー({lobby.Id})を作成しました");

        // 作成したロビー情報を保存
        isCreated = true;
        JoinedLobbyID = lobby.Id;

        return lobby;
    }
    catch (LobbyServiceException e) {
        Debug.LogException(e);
        throw e;
    }
}
ロビー検索.cs
/// <summary> ロビー検索 </summary>
public async Task<IReadOnlyList<Lobby>> SearchLobbies()
{
    // 検索オプション指定
    QueryLobbiesOptions options = new QueryLobbiesOptions {
        Count = queryCount,        // 検索結果数

        // フィルター指定
        Filters = new List<QueryFilter> {
            new QueryFilter(QueryFilter.FieldOptions.AvailableSlots, "0", QueryFilter.OpOptions.GT),        // 満員のロビーは検索しない
        },

        // ソート順指定
        Order = new List<QueryOrder> {
            new QueryOrder(false, QueryOrder.FieldOptions.AvailableSlots),									// 空き人数の降順で並び変え
        },
    };

    try {
        // 検索
        QueryResponse response = await LobbyService.Instance.QueryLobbiesAsync(options);
        return response.Results;
    }
    catch (LobbyServiceException e) {
        throw e;
    }
}

🔗参考リンク集

● MatchMaker(編集中)

  • マッチング関係の機能を扱える
  • プレイヤーのランクに応じたマッチングなどを簡単に実装できる

● Multiplayer Tools

  • プロファイラーや、ネットワークのシミュレーションができる機能などがまとまったツール群

プロファイラー

  • 送信、受信量とかをゲーム画面上で確認できる
    image.png

● Multiplayer Play Mode (MPPM)

  • Editor上で複数のゲームウィンドウやコンソールを表示できる機能
  • プレイヤーに対してタグを付与して、チーム分けしたりできる
  • ビルドする手間が減るのですごく便利ですが、プレイヤーごとにプロジェクト用のフォルダが作成されるので、容量取られるのが欠点
  • また、Unityバージョン2023.1以降でのみ利用可能
  • 現状ベータ版ですが、すごく便利

使用例

  • こんな感じでエディター上で2人分使えるので、ものすごく便利!!
    ConnectScene_.gif
    • コンソールビューやシーンビューもプレイヤーごとに作成されるので、混同しなくてわかりやすい!

  • Unity Authenticationとの併用には注意が必要
    • 普通に匿名サインインすると、同じIDが反映されてしまうので、プレイヤーごとに異なるIDを割り当てる必要がある

    • 一番簡単なのは、プレイヤーがゲームを起動するたびにIDを変更する方法

      .cs
      protected override async void Awake()
      {
          base.Awake();
      
          // サービス初期化
          await UnityServices.InitializeAsync();
      
          AuthenticationService.Instance.SignedIn += () => {
              print($"{AuthenticationService.Instance.PlayerId} was signedin.");
          };
      
      #if UNITY_EDITOR
          // リセット(MPPM用)
          AuthenticationService.Instance.ClearSessionToken();
      #endif
      
          await AuthenticationService.Instance.SignInAnonymouslyAsync();
      
          SetEvents();
      }
      
      • ただ、この方法だとIDが変更されて起動するたびにオンラインで保存されたデータなどがリセットされる
      • 今後のMPPMのアップデートに期待…?

■ さいごに

  • 情報量が多く、学習コスト高めですが、汎用性高めなのでPhotonよりも便利だと思います
  • でも結構コストかかるんで、簡易的なプロジェクトはPhotonでいいかもです

● 参考

UGS

Netcode

参考動画

Unity Authenticatoin

Relay

参考動画

Lobby

参考動画

Other

Unity TransPort

Multiplayer Tools

MPPM


1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2