こんにちは、Japan Developer Support Core チームの近澤です。
PlayFab では Leaderboard (ランキング) を取得する API を用途に応じて複数ご用意しております。
これらの動作について、弊社へよくお問い合わせいただく内容について、ご説明いたします。
Leaderboard を取得する API の種類
現在以下の API をご用意しております。
API | URL |
---|---|
GetLeaderboard | Client / Server |
GetLeaderboardAroundPlayer | Client / Server ※ |
GetFriendLeaderboard | Client / Server |
GetFriendLeaderboardAroundPlayer | Client |
GetCharacterLeaderboard | Client / Server |
GetLeaderboardAroundCharacter | Client / Server |
GetLeaderboardForUserCharacters | Client / Server |
※ GetLeaderboardAroundPlayer は Server API では GetLeaderboardAroundUser という名称ですが、これらは同じ機能です。
API 使用時の注意点
ランキング機能が必要なシチュエーションは、主に以下の2通りです。
- ランキング上位のプレイヤーを表示するとき
- 特定のプレイヤーのランキングを表示するとき
前者は、GetLeaderboard 系 API で取得できます。
後者は GetLeaderboardAroundPlayer 系 API で取得できます。
GetLeaderboardAroundPlayer 系 API は対象のプレイヤーやキャラクターの周辺 100 件 (上位 50 件、下位 50 件) まで取得することができます。
しかしながら、これらの機能で厳密なランキングを取得されたいという場合には、以下の事項が問題になることがあります。
1,000 位以降に推定値が使用される動作について
GetLeaderboard 系 API ならびに GetLeaderboardAroundPlayer 系 API ではプレイヤー数のスケーラビリティとパフォーマンスを維持する目的で、1,000 位以降の順位については特定のアルゴリズムに基づく推定値を返します。
厳密に正確な順位を返すものではありません。
この設計は、計算コストとのトレードオフの結果、1,000 位以上で厳密な順位が必要になるケースが多くないことを想定したものですが、もし全てのランキングで正確な値が必要な場合は、残念ながら回避策はありません。
この動作は、現在 Private Preview である Leaderboard v2 では改善される予定ですので、どうしても PlayFab で厳密な順位を取得したいということであれば、個別に弊社へご相談いただき、Private Preview 機能を有効にすることも可能です。
推定値の詳細は以下の通りです。
推定値は、通常のランキングと同じく、対象のプレイヤーのスコアが変化した場合、即座に順位に反映されます。
推定値の計算方法は、一定数のプレイヤーをサンプリングし、それらのスコアと比較した相対的な順位を計算する仕組みとなります。
このサンプルセットは、Leaderboard に新しいプレイヤーが追加されたときに変化することがありますが、それ以外は同じサンプルセットが使用されます。
このサンプルセット内の相対的な順位に影響を与えない程度の微々たるスコア変化の場合、プレイヤーのランク推定値は変化しない場合があります。
アルゴリズム上、特にスコアの差が僅差の場合に実際の順位と乖離が生じやすくなっており、例えば、スコアが 1 〜 5,000 の範囲に分布している場合と 1 〜 5,000,000 の範囲に分布している場合とでは、前者の方が実際の順位との乖離が生じやすくなります。
このずれにより、推定値が 1,000 位未満の値になる可能性もあります。
この推定値はランキングを取得する PlayFab ID ごとに結果が異なります。
同じ API、同じ PlayFab ID を使用した場合は、常に同じ結果を返す動作となります。
ランキング同率スコア時の順位付けについて
GetLeaderboardAroundPlayer 系 API では、クエリに指定したプレイヤーが同率スコアのトップの Position として返す動作となります。
そのため、特定のプレイヤーに自身のランキングを開示する場合には、特に問題等無く API の結果をそのままご利用いただけるかと存じます。
しかしながら、GetLeaderboard 系 API や GetLeaderboardAroundPlayer 系 API のクエリに指定されていない同率スコアのプレイヤーの Position は、スコアに変化が無かったとしても一意に定まることは保証されません。
厳密には、常に変化する可能性があるものとお考えいただく必要があります。
なお、この動作も、現在 Private Preview である Leaderboard v2 では改善される予定です。
そのため、一貫した Position を決定されたい場合、この動作は問題となります。
その際の回避策として、下記の二つが考えられます。
回避策 1
前述の通り、厳密には同率スコアのプレイヤーの並びは変化する可能性がありますので、これを回避するには同率のスコアのプレイヤーが生じないように制御する必要があります。
これを実現するため、32 bit 値であるスコアの上位ビットをスコアの値として利用し、下位ビットをタイムスタンプのような一意の値として、ユーザー間の重複が生じないように制御します。
例) 16 bit ずつに分け、(1) スコアが 0x1234 (4660)、(2) 同率回避用の値が 0xABCD (43981) の場合
0x12 0x34 0xAB 0xCD
└──┘ └──┘ └──┘ └──┘
(1) (2)
本来のスコアとして利用可能な値のレンジが少なくなることと、同率回避用の一意の値をどのように生成するかといった点はご留意いただく必要があります。
回避策 2
GetLeaderboard 系の API で取得される Position は厳密には確定的ではありませんが、短い期間の間に同一のエンドポイントから API が実行される限りにおいては、結果にばらつきが生じる可能性は低いものと考えられます。
例1) GetLeaderboard 系で Player を指定しない場合の結果
Position Player Score
0 J 14
1 I 13
2 H 12
3 G 11
4 F 11
5 E 10
6 D 10
7 C 10
8 B 10
9 A 9
例2) GetLeaderboardAroundPlayer 系で Player C を指定した場合の結果
C が同率の中でトップの Position となります
Position Player Score
0 J 14
1 I 13
2 H 12
3 G 11
4 F 11
5 C 10
6 E 10
7 D 10
8 B 10
9 A 9
例 2) の情報をもとに、C 以下の順位のPlayer を確認するため Position 6 以降の情報を確認しようとしても、例1) のとおり、C が Position 7 として現れる結果となります。
これを避けるには、以下のような順で処理を実行します。
- GetLeaderboardAroundPlayer 系 API で C の Position を確認します。(5 が取得されます)
- GetLeaderboard API を C の Position -1 (= 4) を指定して実行します。この結果に含まれる C の Position (= 7 となるはずです) を C の本来の Position とみなして、以降の処理を行います。
- GetLeaderboard API で Position 8 を指定して実行すれば、C を含まない B 以降の Position の Player の順位が取得されます。
参考
Introduction to Leaderboards v2 - PlayFab | Microsoft Learn
Leaderboard positions wrong / duplicated when viewing multiple leaderboards - Playfab Community
本ブログの内容は弊社の公式見解として保証されるものではなく、開発・運用時の参考情報としてご活用いただくことを目的としています。もし公式な見解が必要な場合は、弊社ドキュメント (https://docs.microsoft.com や https://support.microsoft.com) をご参照いただくか、もしくは私共サポートまでお問い合わせください。