> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用排行榜執行更多操作

> PlayFab 排行榜進階功能：建置多欄排行榜、增強的平手決勝、外部實體，以及查詢玩家周圍的排名。

在本教學課程中，我們將介紹此服務所提供的進階功能，例如建立多欄
排行榜、增強的平手決勝，以及查詢排行榜的多種方式。

在此範例中，我們假設您已熟悉[建立基本排行榜](/zh-TW/services/playfab/community/leaderboards/create-basic-leaderboard)中介紹的所有內容。
我們將以高度競爭的射擊遊戲為例，說明這些新功能如何協助我們解決
一些問題。在這款遊戲中，有一個名為團隊死鬥的模式，由兩支隊伍互相對戰。最先達到
75 次擊殺的隊伍就是贏家。這款遊戲並非以單一分數為玩家排名，而是根據
擊殺、助攻和死亡次數來決定誰是最佳玩家。

## 建立多欄排行榜定義

要開始此範例，我們需要建立比先前更複雜的排行榜定義。
我們將定義多個欄來對應遊戲的關鍵面向：擊殺、助攻和死亡。
下列範例示範如何使用 C# SDK 建立排行榜定義。

```C# theme={null}
public static async Task CreateLeaderboardDefinitionAsync(PlayFabAuthenticationContext context, string leaderboardName)
{
    PlayFabProgressionInstanceAPI leaderboardsAPI = new PlayFabProgressionInstanceAPI(context);
    CreateLeaderboardDefinitionRequest leaderboardDefinitionRequest = new CreateLeaderboardDefinitionRequest()
    {
        AuthenticationContext = context,
        Name = leaderboardName,
        SizeLimit = 1000,
        EntityType = "title_player_account",
        VersionConfiguration = new VersionConfiguration()
        {
            MaxQueryableVersions = 1,
            ResetInterval = ResetInterval.Manual,
        },
        Columns = new List<LeaderboardColumn>()
        {
            new LeaderboardColumn()
            {
                Name = "Eliminations",
                SortDirection = LeaderboardSortDirection.Descending,
            },
            new LeaderboardColumn()
            {
                Name = "Assists",
                SortDirection = LeaderboardSortDirection.Descending,
            }
            new LeaderboardColumn()
            {
                Name = "Deaths",
                SortDirection = LeaderboardSortDirection.Ascending,
            }         
        }
    };

    PlayFabResult<PlayFab.LeaderboardsModels.EmptyResponse> createLbDefinitionResult = await leaderboardsAPI.CreateLeaderboardDefinitionAsync(leaderboardDefinitionRequest);
}
```

現在，讓我們說明此範例的一些重要元素：

* `SizeLimit`：此參數用於限制排行榜可擁有的列數。此處的值僅為範例。
* `VersionConfiguration`：此參數可讓我們為排行榜進行版本控制。如需詳細資訊，
  請參閱此頁面：[季節性排行榜](/zh-TW/services/playfab/community/leaderboards/seasonal-leaderboards)
* `Columns`：此參數可讓我們定義多個欄，每個定義最多 5 個。如您所見，我們設定了 Eliminations、Assists 和 Deaths。
  這裡的一個重要元素是 `SortDirection` 參數，可讓我們決定排行榜的排序方式。
  在此範例中，擊殺和助攻次數較多 (SortDirection = Descending) 且
  死亡次數較少 (SortDirection = Ascending) 的玩家，排名會較高。

如需其他參數或如何管理排行榜定義的詳細資訊，請參閱[建立基本排行榜](/zh-TW/services/playfab/community/leaderboards/create-basic-leaderboard)。

## 使用外部實體

排行榜服務可作為獨立元件使用，支援使用僅在遊戲情境中才有意義的外部實體。如果您的玩家身分識別未與 PlayFab 登入繫結，您仍然可以使用排行榜服務。PlayFab 系統之外的排行榜項目，其實體類型必須是 *external*。entityId 則是玩家在您系統中的身分識別。在這些情況下，排行榜上的*所有*項目都必須是 *external* 實體。

## 將資料新增至排行榜

現在我們已經建立了排行榜，接下來要新增資料。與先前此主題的教學課程主要的差異在於，
現在我們需要在同一列中新增三個不同的分數。下列範例示範如何使用 C# SDK
將資料新增至排行榜。

```C# theme={null}
public static async Task UpdateLeaderboardForPlayer(PlayFabAuthenticationContext context, string leaderboardName, string entityId, int score)
{
    PlayFabProgressionInstanceAPI leaderboardsAPI = new PlayFabProgressionInstanceAPI(context);
    UpdateLeaderboardEntriesRequest updateLeaderboardRequest = new UpdateLeaderboardEntriesRequest()
    {
        Entries = new List<LeaderboardEntryUpdate>()
        {
            new LeaderboardEntryUpdate()
            {
                EntityId = entityId,
                Scores = new List<string> { score.ToString(), (score + 1).ToString(), (score + 2).ToString() },
                Metadata = "metadata",
            }
        },
        AuthenticationContext = context,
        LeaderboardName = leaderboardName,
    };

    PlayFabResult<PlayFab.LeaderboardsModels.EmptyResponse> updateResult = await leaderboardsAPI.UpdateLeaderboardEntriesAsync(updateLeaderboardRequest);
}
```

需要注意的一件重要事情是，Scores 參數被賦予三個值。為任何項目指定的分數清單長度，必須與排行榜定義的欄數相符。每個值都必須是有效的 64 位元整數 (使用字串表示法只是為了確保所有用戶端都能處理 64 位元的值)。

## 從排行榜擷取資料

現在我們將了解查詢排行榜的不同方式。每種方式都有其特定用途，目的是
協助開發人員取得他們需要在遊戲中顯示的玩家。

### 取得實體周圍的排行榜

這種查詢排行榜的特定方式，可讓我們取得接近特定實體的排行榜區段。這種情境的實際
應用是，當我們有一個龐大的排行榜，而只想向遊戲中的活躍玩家
顯示相關資訊時。如果玩家位於第 1000 名，我們可以顯示其附近的玩家，而非排名最前面的玩家。
下列範例示範如何使用 C# SDK 查詢實體周圍的排行榜。

```C# theme={null}
public static async Task<List<EntityLeaderboardEntry>> GetLeaderboardAroundEntity(PlayFabAuthenticationContext context, string leaderboardName, string entityId)
{
    PlayFabProgressionInstanceAPI leaderboardsAPI = new PlayFabProgressionInstanceAPI(context);
    GetLeaderboardAroundEntityRequest getLbRequest = new GetLeaderboardAroundEntityRequest()
    {
        LeaderboardName = leaderboardName,
        AuthenticationContext = context,
        Entity = new PlayFab.LeaderboardsModels.EntityKey()
        {
            Id = entityId,
            Type = EntityType
        },
        MaxSurroundingEntries = 20,
    };

    PlayFabResult<GetEntityLeaderboardResponse> lbResponse = await leaderboardsAPI.GetLeaderboardAroundEntityAsync(getLbRequest);
    
    return lbResponse.Result.Rankings;

}
```

這裡最重要的元素是 `MaxSurroundingEntries`，可讓我們從排行榜中擷取排名在特定實體
周圍的實體。例如，如果我們有一位位於第 100 名的玩家，而我們使用
`MaxSurroundingEntries` = 20，則會擷取第 90 名到第 110 名的玩家。如果玩家位於排行榜的
頂端，則會擷取前 20 名的結果。如果玩家位於底部，則會擷取最後 20 名的結果。除了排行榜頂端和底部的位置之外，API 會盡量確保所要求排名的中心實體，位於擷取位置的中央。

### 取得實體的排行榜

此 API 提供了另一種查詢排行榜的方式。它適用於我們想要在排行榜中搜尋多個實體
並加以排序的情況。下列範例示範如何使用 C# SDK
查詢實體清單的排行榜。

```C# theme={null}
public static async Task<List<EntityLeaderboardEntry>> GetLeaderboardForEntities(PlayFabAuthenticationContext context, string leaderboardName, List<string> entityIds)
{
    PlayFabProgressionInstanceAPI leaderboardsAPI = new PlayFabProgressionInstanceAPI(context);
    GetLeaderboardForEntitiesRequest getLbRequest = new GetLeaderboardForEntitiesRequest()
    {
        LeaderboardName = leaderboardName,
        AuthenticationContext = context,
        EntityIds = entityIds,
    };

    PlayFabResult<GetEntityLeaderboardResponse> lbResponse = await leaderboardsAPI.GetLeaderboardForEntitiesAsync(getLbRequest);

    return lbResponse.Result.Rankings;
}
```

### 取得好友排行榜

在某些情況下，有些休閒玩家可能會來玩遊戲。他們可能離排行榜頂端很遠，但在他們的好友之間，正在進行一場競賽。透過此 API，我們可以查詢排行榜並找出玩家的好友。

```C# theme={null}
public static async Task<List<EntityLeaderboardEntry>> GetFriendLeaderboardForEntity(PlayFabAuthenticationContext context, string leaderboardName, string entityId)
{
    PlayFabProgressionInstanceAPI leaderboardsAPI = new PlayFabProgressionInstanceAPI(context);
    GetFriendLeaderboardForEntityRequest getLbRequest = new GetFriendLeaderboardForEntityRequest()
    {
       LeaderboardName = leaderboardName,
       Entity = new PlayFab.LeaderboardsModels.EntityKey()
       {
           Id = entityId,
           Type = EntityType
       },
    };

    PlayFabResult<GetEntityLeaderboardResponse> lbResponse = await leaderboardsAPI.GetFriendLeaderboardForEntityAsync(getLbRequest);
  
    return lbResponse.Result.Rankings;
}
```

從 PlayFab 服務取得好友的方式有很多種。如需可用參數的詳細資訊，請參閱 [API 參考](/zh-TW/services/playfab/community/leaderboards/api-reference)。

### 增強的平手決勝

以我們高度競爭的射擊遊戲為例，在某些情況下，可能會有多位玩家擁有相同的
擊殺次數。在這些情境中，我們需要用不同的方式來為這些情況決勝。這就是增強的平手決勝
功能派上用場的情境。

建立排行榜定義時，您可以擁有多個欄。新增欄的方式將決定我們如何
排序以及在某些情境中決勝。這裡有一個優先順序，第一個新增的欄最重要，接著是第二個，
依此類推。套用到我們的範例，就是每當擊殺次數平手時，第二個準則是助攻次數，
而最後的準則是死亡次數。在仍然平手的極端情況下，則預設會使用時間戳記，
也就是最先達成分數的人。

\| 排名     | 實體識別碼                         | 擊殺|  助攻        | 死亡 | LastUpdated\
\|----------------------|------------------------------------|-------------------|--------------------------
|1 | "player 3" | 103               |24 | 15|"2024-08-27T20:24:36.738Z"
|2 | "player 2" | 102               | 30| 20 |"2024-08-27T20:24:29.251Z"
|3 | **"player 1"** | 100               | 25 |18 |"2024-08-27T19:52:26.642Z"\
|4 | **"player 4"** | 100               | 25 | 18 |"2024-08-27T20:24:44.552Z"
|4 | **"player 5"** | 100               | 25 | 19 |"2024-08-27T20:25:47.552Z"

在此範例中，有三位玩家平手：

* "player 5"：儘管擊殺和助攻次數相同，但其死亡次數較多，這表示其位於
  排行榜的底部。
* "player 4"：此玩家的死亡次數比 "player 5" 少，且與 "player 1" 相同，但 player 1 較早達到這些數字。
* "player 1"：儘管與 "player 4" 的數字相同，但此玩家是遊戲中第一個達成此分數的人，因此在此平手決勝情境中排名較高。

## 結論

在本教學課程中，我們學到了如何執行下列作業：

* 建立多欄排行榜。
* 查看多種查詢方式。
* 了解增強的平手決勝機制。

## 另請參閱

* [建立基本排行榜](/zh-TW/services/playfab/community/leaderboards/create-basic-leaderboard)。
* [季節性排行榜](/zh-TW/services/playfab/community/leaderboards/seasonal-leaderboards)。
* [限制 ](/zh-TW/services/playfab/community/leaderboards/limits-leaderboards)。
* [配額 ](/zh-TW/services/playfab/community/leaderboards/quota-leaderboards)。
* [依統計資料為玩家排名](/zh-TW/services/playfab/community/leaderboards/leaderboards-linked-to-stats)。
* [群組排行榜](/zh-TW/services/playfab/community/leaderboards/group-leaderboards)。
* [手動層級](/zh-TW/services/playfab/community/leaderboards/manual-tiers)。
* [將額外資料新增至排行榜](/zh-TW/services/playfab/community/leaderboards/metadata-leaderboards)。
* [API 參考](/zh-TW/services/playfab/community/leaderboards/api-reference)。
* [排行榜與 Cloudscript](/zh-TW/services/playfab/community/leaderboards/leaderboards-cloudscript)。
* [搭配 Playstream 的排行榜](/zh-TW/services/playfab/community/leaderboards/leaderboards-with-playstream-and-telemetry)


## Related topics

- [群組排行榜](/zh-TW/services/playfab/community/leaderboards/group-leaderboards.md)
- [排行榜 API 參考](/zh-TW/services/playfab/community/leaderboards/api-reference.md)
- [使用 Azure Functions 的排行榜](/zh-TW/services/playfab/community/leaderboards/leaderboards-cloudscript.md)
- [季節性排行榜](/zh-TW/services/playfab/community/leaderboards/seasonal-leaderboards.md)
- [手動層級排行榜](/zh-TW/services/playfab/community/leaderboards/manual-tiers.md)
