Beta版のUnity Gaming Servicesを導入して軽く触ってみる

本記事は[Craft Egg Advent Calendar 2021](https://qiita.com/advent-calendar/2021/craftegg)の12/4の記事です。
12/3の記事は@Tomy_0331さんの「新卒2年目までに学んだ、コーディングで意識すること」でした。

# はじめに
株式会社Craft EggでUnityクライアントエンジニアをしている山元です。
アドベントカレンダーを書くということで何かいいネタがないかと探していたところ、最近 Unity Gaming Services のBeta版がリリースされていたので触ってみた記事になっております。

# Unity Gaming Services とは
「バックエンド、マネタイズ、ユーザー獲得、プレイヤーエンゲージメントなど、ゲームクリエイターが必要とするすべての機能を提供する新しいプラットフォーム」のようです。

11/22にBeta版がリリースされた新機能になっておりマルチプレイ機能、Vivoxよる音声通話など様々な機能が入っています。

https://unity.com/ja/solutions/gaming-services

#早速触って試してみる
今回はUnity Gaming Services を使用してプレイヤーが Lobby に参加するところまでを試してみようと思います。
### 検証環境
```
Mac Catalina
Unity 2021.1.0b12
Unity Authentication 1.0.0-pre.6
Unity Lobby 1.0.0-pre.6
UniTask 2.2.5
```

##Gaming Servicesの準備
PackageManager, Unity Editor, Unity DashBoard にてそれぞれ準備を行います。
###PackageManager
Unity Editor で Gaming Services の機能を利用するため manifest.json に以下のPackageを追加します。

```
"dependencies": {
    "com.unity.services.authentication": "1.0.0-pre.6",
    "com.unity.services.lobby": "1.0.0-pre.6",
 }
```

###Unity Editor

Gaming Services の Unity Project ID を作成します。
手順：
・ UnityEditor で Project Settings > Services を開く
・ Organizations から自分のアカウントを選択する
・ Create Project ID ボタンをクリック
・ 一番下の項目にある13歳以下の子供を対象にしているかの設定で Yes No どちらかを選ぶ
・ 右下にあるSaveボタンを押して完了
![スクリーンショット 2021-11-28 17.51.27のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/21d88113-5cc0-cf34-36da-3ca6a5ee40dc.png)
Gaming Services を利用するための Unity Editor 側の準備は以上になるので Unity DashBoard 側の準備に移ります。

###Unity DashBoard
ダッシュボードでは Lobby 内でプレイヤーがマッチングするために必要な機能を有効にする設定を行います。

https://dashboard.unity3d.com/

手順：
・ Unity Dashboard 側で先ほど作成した Unity Project を選択する
・ 今回はプレイヤーのマッチング機能を試すので左タブ下の方にある Multiplayer を選択する
・「Lobby」「Relay」機能それぞれ Get Started から手順通りに進み機能を ON にする
![スクリーンショット 2021-11-28 18.05.33のコピーa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/fe86c622-6e7f-f78a-3b8a-9abb8f8bf511.png)

これでダッシュボード側の準備も完了しました。
これから実際にコードを書いてロビーを作成、参加していこうと思います。

##実装

###サインイン
Unity Gaming Services は何をするにしても Unity Authentication を使用して認証を通す必要があります。
なのでまずはUnity Authentication で匿名サインイン処理を行っていきましょう。

https://docs.unity.com/authentication/IntroUnityAuthentication.htm

``` csharp
private async void Start()
{
    // Unity Gaming Services の初期化処理
    await UnityServices.InitializeAsync();
    Debug.Log(UnityServices.State);
    
    await SignInAnonymouslyAsync();
}
```

``` csharp
/// <summary>匿名サインインする処理</summary>
private async UniTask SignInAnonymouslyAsync()
{
    try
    {
        await AuthenticationService.Instance.SignInAnonymouslyAsync();
        Debug.Log("匿名サインイン成功！");
    }
    catch (AuthenticationException ex)
    {
        // 認証エラー時の例外
        Debug.LogException(ex);
    }
    catch (RequestFailedException exception)
    {
        // リクエストエラー時の例外
        Debug.LogException(exception);
    }
}
```
![スクリーンショット 2021-11-28 18.29.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/2df60847-5887-fd01-4616-5be6a774821e.png)
サインイン成功，サインイン失敗，サインアウト時のコールバックをそれぞれ登録することもできます。
`AuthenticationService.Instance.SignedIn`
`AuthenticationService.Instance.SignInFailed`
`AuthenticationService.Instance.SignedOut`

###ロビーの作成

https://docs.unity.com/lobby/unity-lobby-service-overview.htm

``` csharp
private async void Start()
{
    // Unity Gaming Services の初期化処理
    await UnityServices.InitializeAsync();
    Debug.Log(UnityServices.State);
    
    await SignInAnonymouslyAsync();

    var lobby = await CreateLobbyAsync("test lobby", 2);

    if (lobby == null) return;

    Debug.Log($"ロビー作成成功！ Id:{lobby.Id}, Name:{lobby.Name}");
}
```

```csharp
/// <summary>ロビーを作成する処理</summary>
/// <param name="lobbyName">ロビー名</param>
/// <param name="maxPlayers">ロビーの最大プレイヤー数</param>
/// <returns>作成したロビー</returns>
private async UniTask<Lobby> CreateLobbyAsync(string lobbyName, int maxPlayers)
{
    try
    {
        return await Lobbies.Instance.CreateLobbyAsync(lobbyName, maxPlayers);
    }
    catch (LobbyServiceException ex)
    {
        Debug.LogException(ex);
    }

    return null;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/0e572db5-3257-484e-7bdb-0f7ffe5d9f29.png)

今回はお試しなので指定していませんが Lobbies.Instance.CreateLobbyAsync の第三引数に CreateLobbyOptions という細かいオプションを渡すこともできます。

```csharp 
public class CreateLobbyOptions 
{
    // プライベート用のフラグ
    public bool? IsPrivate { get; set; }

    // ロビー製作者の情報
    public Player Player { get; set; }

    // ゲーム固有のプロパティも設定できる
    public Dictionary<string, DataObject> Data { get; set; }
}
```

###ロビーの入室

Unity Editorだけでは検証することができないのでアプリケーションをビルドしてロビーを作成した状態で検証します。

``` csharp
private async void Start()
{
    // Unity Gaming Services の初期化処理
    await UnityServices.InitializeAsync();
    Debug.Log(UnityServices.State);
    
    await SignInAnonymouslyAsync();

    var lobby = await QuickJoinLobbyAsync();
    if (lobby != null)
    {
        Debug.Log($"ロビー入室成功！ Id:{lobby.Id}, Name:{lobby.Name}");
        return;
    }
    
    // ロビーに参加できなかったので作成する
    lobby = await CreateLobbyAsync("test lobby", 2);

    if (lobby == null) return;

    Debug.Log($"ロビー作成成功！ Id:{lobby.Id}, Name:{lobby.Name}");
}
```

```csharp
/// <summary>条件に応じた適当な部屋に素早く入室する処理</summary>
/// <returns>入室したロビー</returns>
private async UniTask<Lobby> QuickJoinLobbyAsync(QuickJoinLobbyOptions options = null)
{
    try
    {
        return await Lobbies.Instance.QuickJoinLobbyAsync(options);
    }
    catch (LobbyServiceException ex)
    {
        Debug.LogException(ex);
    }

    return null;
}
```

ロビーに入室できた時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/a55d7435-d2cd-2e74-bc2e-38e6676a8eb6.png)
ロビーに入室できなかった時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332397/ddacb0ae-ded8-095d-0f6f-4f60ba3a2051.png)

無事ロビーに入室するところまで実装することができました。

#まとめ

今回は Unity Gaming Services を使って、ロビー作成、参加というマルチプレイの基本的な部分の実装を行ってみました。
Unity Gaming Services はマネタイズ、プレイヤーエンゲージメントなど広い領域をサポートするようなので今後のアップデートに注目していこうと思います。

今回のLobby実装はUnity公式にサンプルプロジェクトがあるので気になった方は触ってみると良いかもしれません！
※サンプルプロジェクトでは Vivox が使用されているのでダッシュボードにて「Vivox」を ON にする必要があります

https://github.com/Unity-Technologies/com.unity.services.samples.game-lobby/tree/acfc50b89aa552d3784a9ae1f8bd97f222be7a70

ここまで読んで頂きありがとうございました！

[Craft Egg Advent Calendar 2021](https://qiita.com/advent-calendar/2021/craftegg) 明日は@ryousangataの記事になります！