Open6

Unity Gaming Servicesを利用する

sonailsonail

事前準備

プロジェクトにGaming Services(以下UGS)を登録する

編集中につき以下参照(SDKのセットアップまで)
Unity Gaming Services とは?匿名ログインと Cloud Save を試してみた

Editor上でプロジェクトをリンクする

[ProjectSettings] -> [Services]を開く
Organization
ProjectをWeb上で作成している場合は[Use an existing Unity Project ID]、そうでない場合は[Create Project ID]

既に作成しているのでOrganizationとProjectsを選択して[Link ProjectID]
Link

sonailsonail

Authentication

注:事前準備をしていないと以下のエラーが出ます

[Authentication]: Request failed: 400, {"title":"INVALID_PARAMETERS","detail":"Valid ID Domain not specified","details":[],"status":400}

匿名ログイン

GamingServicesの初期化

ログインとかをする前にまずUnityServicesの初期化を呼ぶ必要があります。Task化されているのでasync void Start()とかで初期化を待てますね。
optionsはナシでも問題ありません。optionsについてはこちらをご覧ください。基本的には環境切り替えなどに対応するために用意されてるんでしょうか。

        await UnityServices.InitializeAsync(options);

ログイン

初期化後に匿名ログインを行います。以下はドキュメントそのままのコードです

            try
            {
                await AuthenticationService.Instance.SignInAnonymouslyAsync();
                Debug.Log("Sign in anonymously succeeded!");

                // Shows how to get the playerID
                Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");

            }
            catch (AuthenticationException ex)
            {
                // Compare error code to AuthenticationErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(ex);
            }
            catch (RequestFailedException exception)
            {
                // Compare error code to CommonErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(exception);
            }

匿名ログイン成功
成功すると以下のログが表示されます

Sign in anonymously succeeded!

基本的に同じデバイスである限り同じPlayerID(同一アカウント)となります。別デバイスでは引き継ぐことは出来ないようです。
以下を実行してから再度ログインすることで新たな匿名アカウントを作成することができます。

AuthenticationService.Instance.ClearSessionToken() 

ClearSessionToken()はログイン中は実行できないので注意してください

AuthenticationException: Invalid state for this operation. The player is already signed in.

ログアウト

以下のコードでログアウトできます

AuthenticationService.Instance.SignOut();

ここまでで、ログイン/ログアウト/新規作成が行えるようになりました。
とっても簡単でいいですね。
まとめ

イベントを取得する

以下のようにして、ログイン関係のイベントハンドラを登録、利用することができます。

// Setup authentication event handlers if desired
void SetupEvents() {
  AuthenticationService.Instance.SignedIn += () => {
    // Shows how to get a playerID
    Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");

    // Shows how to get an access token
    Debug.Log($"Access Token: {AuthenticationService.Instance.AccessToken}");

  };

  AuthenticationService.Instance.SignInFailed += (err) => {
    Debug.LogError(err);
  };

  AuthenticationService.Instance.SignedOut += () => {
    Debug.Log("Player signed out.");
  };
 
  AuthenticationService.Instance.Expired += () =>
    {
        Debug.Log("Player session could not be refreshed and expired.");
    };
}

外部プラットフォームログイン

機会があったら試します...

sonailsonail

Cloud Save

クラウド上にプレイヤーデータを保存できる機能。


保存できるデータ

  • Maximum 16 KB in size per slot
  • Maximum 255 characters per slot name
  • Maximum 200 data slots per player
  • JSON serializable data

データの保存/復元/削除

保存するデータを作る

上述の保存できるデータならなんでもいいですが、例としてユーザーデータをJsonで保存することにします。

    [Serializable]
    public class UserData
    {
        public string UserName;

        public UserData(string name)
        {
            this.UserName = name;
        }
        
        public override string ToString()
        {
            return $"{UserName}";
        }
    }

名前のみのミニマムなセーブデータにします。

データを保存する

        public async void SaveUserData(string name)
        {
            var data = new UserData(name);
            await SaveData.ForceSaveAsync(new Dictionary<string, object> {{"data", data}});
        }

Json Serializableであるためクラスをそのまま保存できます。

データを復元する

        public async Task<UserData> LoadUserData()
        {
            UserData data = null;
            try
            {
                var dic = await SaveData.LoadAsync(new HashSet<string> {"data"});
                data = JsonUtility.FromJson<UserData>(dic["data"]);
            }
            catch (CloudSaveException)
            {
                Debug.LogError("[CloudSaveException]");
            }
            catch (KeyNotFoundException)
            {
                Debug.LogError("[KeyNotFoundException]");
            }

            return data;
        }

一応例外をcatchしていますがこのあたりはご自由に。
データが見つからないとKeyNotFoundException、リクエストに失敗するとCloudSaveExceptionになります。

データを削除する

キーから削除します

        public async void DeleteUserData()
        {
            await SaveData.ForceDeleteAsync("data");
        }

実際に保存、復元、削除を行ったgifが以下です
SaveTest

PlayerIDと紐づいているため、同一のIDでロードすると正しく復元されることが分かります(永続化)
Load


データの確認

Dashboard上の[LiveOps]->[PlayerManager]のplayer ID欄に検索したいIDを入力することでデータを見ることができます。
プレイヤー一覧を見ることはできないのかな?
Dashboard

sonailsonail

Environment

いわゆる本番環境や開発環境を切り替えるために利用できる機能です。
何気にドキュメントを探しにくい。


環境の追加

開発(dev)環境を作成してみましょう。
Dashboardの[Projects]->[Environments]を開きAdd environmnet
Add
Add2

devが増えました。10個制限を解除するには?
情報が必要です
Added


環境の切り替え

Dashboard

見たいサービスを選んでドロップダウンから選択するだけ
Dropdown

ランタイム

InitializationOptionsに環境名をセットしてGaming Services初期化時に渡すだけ。
環境の切り替えはエディタ拡張で出来たほうが良いのでstring指定ではなくEnumを用意すると良いでしょう。

        var options = new InitializationOptions();
        options.SetEnvironmentName("dev");
        await UnityServices.InitializeAsync(options);

トラブル発生

Cloud Dataを試しプレイヤーは見つかるもデータが見つからない!(Webのみ、ロードはできる)
また、同一デバイスだとどの環境でも同じPlayerIDになる模様(これはむしろありがたいかも)

しばらく待ったらDashboardのリロードが走り表示されるようになった。
環境作成してからラグがあるのか、データが反映されるまでラグがあるのか...
いずれにせよ、環境を作成してからDashboardでデータを確認できるまでは時間がかかりそうだ。

sonailsonail

Cloud Code

サーバーサイドのプログラムをクラウド上に置ける機能。アンチチートやAPI作成が主目的?
サーバー時間を利用したコードを書くなら良さそう。ただしスクリプトはJavaScriptのみ


しばらく使わなさそう