認証

【PlayFab】ログイン処理のベストプラクティスとは

playfab-login-best-practices

PlayFab において、色んな種類のログインがありますが、どういった流れのログイン処理がベストなのかについて解説しました。

本記事は、公式ドキュメントのログインの基本とベストプラクティスをもとに作成しています。

ただ公式ドキュメントの内容に沿って解説するだけでは面白くないので、独自の処理や考え方についても合わせて記載しました。

記事を読み終える頃には、ログイン処理についての理解がかなり深まっているはずです。

では、さっそく見ていきましょう。

ログイン処理のベストプラクティスとは

ログインの基本とベストプラクティスをまとめると、以下のことを言っています。

ベストプラクティスまとめ

初回ログイン時は匿名ログインが有効

アカウントを復旧できるように、匿名ログイン以外での認証もすべき

だけど、初回からユーザー名とパスワードの入力は嫌がられる

こんな感じです。

確かに、一般的なスマホゲームの仕組みは上記のようになっている気がしますね。

また、流れとしては以下をログイン処理のベストプラクティスとしています。

playfab-anonymous-login-and-recoverable-login-min

引用:ログインの基本とベストプラクティス

ペンギンくん
ペンギンくん
長いし英語だしよくわからないなぁ。
ねこじょーかー
ねこじょーかー
そう言うと思って、かんたんにしてみたよ!
my-login-best-practices
ペンギンくん
ペンギンくん
おお!だいぶスッキリした。

修正内容は以下のとおりです。

  • 前半に書かれていた、細かいメソッドレベルでの記載はすべて削除
  • 必要だと感じた分岐処理を追加

ということで、順番に解説していきます。

ゲームスタート

ゲームで最初に表示するのは、以下のような「タイトル画面」ですね。

title-menu

ここでタップをしたら、ログイン処理を動作させればよいでしょう。

サイレントログイン

ねこじょーかー
ねこじょーかー
何も考えずにログイン処理を実装する記事を読んでいる前提で進めていきますね!

タイトル画面でタップをしたら、以下のようにサイレントログインをすればよいです。

public void Login()
{
    PlayFabAuthService.OnLoginSuccess += PlayFabAuthService_OnLoginSuccess;
    PlayFabAuthService.Instance.Authenticate(Authtypes.Silent);
}

private void PlayFabAuthService_OnLoginSuccess(LoginResult success)
{
    // 新規作成したかどうか
    if (success.NewlyCreated)
        // ユーザー名を入力する画面に遷移
    else
        // メインメニューに遷移
}

新規ユーザーの場合は、ユーザー名を入力する画面に遷移する分岐処理が必要です。

新規ユーザーかどうかは、LoginResult の NewlyCreated で判断することができます。

ログイン処理は難しくないですね。

プレイヤーの作成と初期化

新規ユーザーの場合は、以下のような画面を用意して、名前を入力してもらう必要があります。

 input-user-name

ここで入力してもらう名前は、タイトルプレイヤーアカウントの表示名にあたります。

player-display-name

プレイヤーのタイトルデータとして名前を管理することもできますが、後でランキングなどを使用するときに表示名が必要になってしまいます。

なので今回は、最初から表示名をユーザー名として管理するようにしました。

表示名の更新は、UpdateUserTitleDisplayNameを使用します。

// 表示名の入力コントロール
[SerializeField] TMP_InputField inputName;

#region プレイヤー表示名の更新
private void UpdateUserTitleDisplayName()
{
    PlayFabClientAPI.UpdateUserTitleDisplayName(new UpdateUserTitleDisplayNameRequest
    {
        DisplayName = inputName.text
    }, result =>
    {
        Debug.Log("プレイヤー名:" + result.DisplayName);
    }, error => Debug.LogError(error.GenerateErrorReport()));
}
#endregion

特に難しい処理はないですね。

表示名の入力チェック

表示名が未入力だったり、100文字くらい入力されても困るので、事前にチェックしておきましょう。

// 表示名の入力コントロール
[SerializeField] TMP_InputField inputName;
// 完了ボタン
[SerializeField] Button inputComp;

public void InputValueChanged()
{
    inputComp.interactable = IsValidName();
}

private bool IsValidName()
{
    // 表示名は、3文字以上25文字以下
    return !string.IsNullOrWhiteSpace(inputName.text)
        && 3 <= inputName.text.Length
        && inputName.text.Length <= 25;
}

PlayFab の制約で、表示名は「3文字以上25文字以下」と決められているのでご注意ください。

ただ、25文字は少し多い気がするので、私は10文字までとしました。

プレイヤーの初期化

ほとんどのゲームでは、プレイヤーに「ランク」と「経験値」をもたせると思います。

ここでは、「ランク1」「経験値0」の情報を初期値として登録してあげる例を書きました。

#region プレイヤーの初期化
private void InitPlayer()
{
    var request = new UpdateUserDataRequest()
    {
        Data = new Dictionary<string, string>
        {
            { "Exp", "0" },
            { "Rank", "1" }
        }
    };

    PlayFabClientAPI.UpdateUserData(request
        , result =>
        {
            Debug.Log("プレイヤーの初期化完了");
        }, error => Debug.LogError(error.GenerateErrorReport()));
}
#endregion

これを実行すると、以下のようにプレイヤーデータが初期化されます。

player-data

かんたんですね。

他にも必要な情報があれば、このタイミングで初期化しておきましょう。

プレイヤーデータの更新と表示名の更新を実行

表示名を入力し終えて完了ボタンを押したあとは、プレイヤーデータの初期化と表示名の更新処理を呼んであげましょう。

// 完了ボタンが押されたときの処理
private void InputComplete()
{
    // プレイヤーデータの初期化
    InitPlayer();

    // 表示名の更新
    UpdateUserTitleDisplayName();
}

ですが、実はこれではNGなんです。

NGの理由について PlayFab のコミュニティサイトに投稿があったので、以下に引用します。

If you mean multiple concurrent requests to the same API’s different fields for the same player. This situation will cause the conflict. This error is targeted to the API, not data fields.

[日本語訳]
同じプレーヤーの同じAPIの異なるフィールドへの複数の同時リクエストを意味する場合。この状況により、競合が発生します。このエラーは、データフィールドではなくAPIを対象としています。

引用:Conflict error when calling UpdateUserTitleDisplayName

つまり、「同じ項目」を別々の API で更新するときに競合が発生するのではありません。

「同じプレイヤー」であれば、たとえ更新する項目が違っても競合が発生する、ということです。

なので順番はどちらでも構いませんが、処理成功時のコールバックでもう片方の処理を呼んで上あげる必要があります。

#region プレイヤーの初期化
private void InitPlayer()
{
    var request = new UpdateUserDataRequest()
    {
        Data = new Dictionary<string, string>
        {
            { "Exp", "0" },
            { "Rank", "1" },
        }
    };

    PlayFabClientAPI.UpdateUserData(request
        , result =>
        {
            Debug.Log("プレイヤーの初期化完了");
            // ------------------------------
            // 処理成功時のコールバックで表示名の更新
            // ------------------------------
            UpdateUserTitleDisplayName();
        }, error => Debug.LogError(error.GenerateErrorReport()));
}
#endregion
ペンギンくん
ペンギンくん
処理が増えたらコールバックの連続になりそうだね…
ねこじょーかー
ねこじょーかー
その場合はサーバー側で処理をすれば、コールバック地獄から抜け出せるよ!

サーバー処理については、Azure関数でCloudScriptを実行する方法で解説しているので合わせてご覧ください。

他の方法で認証済みかどうか

プレイヤー自身の情報は、PlayerProfileModel にもっています。

この中の LinkedAccounts を見ると、どのプラットフォームで認証されているかが取得できます。

例えば Facebook で認証されているかどうかは、以下のように判断すればよいです。

bool facebookAuth = playerProfileModel.LinkedAccounts.Any(x => x.Platform == PlayFab.ClientModels.LoginIdentityProvider.Facebook);

Facebook または Google との連携を促す

公式ドキュメントにかなり細かく手順が記載されているので、以下の記事を参照すれば問題ないと思います。

こちらはまだ試せていないので、もし詰まりポイントなどがあれば後で追記します。

連携後は Android や iOS デバイスとの紐付けを解除

紐付けの解除は、以下の1行でOKです。

PlayFabAuthService.Instance.UnlinkSilentAuth();

ユーザー名とパスワードの登録を促す

ここまで見てきたように、Facebook や Google との連携はやろうと思うとけっこう大変です。

まず最初は、ユーザー名とパスワードで追加認証するのがよいでしょう。

Add Username Password を使って PlayFab のアカウントを作る感じですね。

入力してもらう UI の部分は自分で作る必要がありますが、ロジック的には以下で問題なさそうです。

PlayFabAuthService.Instance.Authenticate(Authtypes.RegisterPlayFabAccount);

 

ペンギンくん
ペンギンくん
ふ〜。長かったけど、理解できたぞ。

最後に

公式ドキュメントの内容に自分の考えをプラスして、ログイン処理のベストプラクティスについて解説しました。

ユーザーが何もしていないのにも関わらず、アカウントにアクセスできなくなってしまったら大変な事態です。

せっかく面白いゲームを作っても、こういうところで信頼を失ってしまってはもったいないですよね。

この記事を参考に、匿名ログインだけでなく他の認証方法にもチャレンジしてみてください。

PlayFab の書籍も好評発売中!
playfab-book

PlayFab のことをもっと皆さんに知ってもらいたくて、合計500ページ以上にもなる書籍を5冊に分けて執筆しました。

私の知識をすべて詰め込んでいるので、ゲーム開発をさらに加速させたい方はぜひご覧ください。

COMMENT

メールアドレスが公開されることはありません。