> ## 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 大廳，以便探索大廳。

讓玩家找到符合特定準則 (例如地圖、難度等級及其他遊戲內特性) 的大廳，對遊戲來說通常很有用。此搜尋功能可讓玩家與想要一起遊玩的人找到想要的遊戲工作階段。

本文說明如何使用 **FindLobbies** 讓玩家尋找大廳。若要了解如何在遊戲中使用尋找大廳，請參閱[常見情境](#common-scenarios)。

<Note>
  不建議使用 **FindLobbies** 實作背景配對。在該情境中，我們強烈建議使用[配對功能](/zh-TW/services/playfab/multiplayer/matchmaking)。否則，您必須透過篩選、排序及其他技術 (例如在搜尋資料欄位中使用隨機值) 來處理所有玩家都嘗試加入相同大廳的衝突。
</Note>

## 了解大廳搜尋屬性與尋找大廳之間的關係

玩家透過定義搜尋屬性讓其大廳可被探索。玩家藉由呼叫 **FindLobbies** 並使用查詢字串，根據目前作用中大廳上所定義的搜尋屬性篩選和排序搜尋結果，來找到這些可探索的大廳。符合這些查詢的大廳會傳回給呼叫的玩家。

如需定義搜尋屬性的詳細資訊，請參閱[建立可搜尋的大廳](/zh-TW/services/playfab/multiplayer/lobby/define-search-keywords)

## 如何使用 FindLobbies

呼叫 **FindLobbies** 時，您可以使用 filter 參數將查詢限制為只傳回符合以大廳自訂搜尋屬性為基礎之某組準則的搜尋結果。

此外，您可以使用排序參數，根據搜尋屬性排序從服務傳回的結果。這很有用，因為服務只會傳回有限數量的搜尋結果。排序可確保您看到最相關的搜尋結果。

<a id="common-scenarios" />

### 常見情境

以下是遊戲中使用 **FindLobbies** 功能的幾種常見方式。

* 為遊戲中特定遊戲模式的遊戲工作階段尋找大廳
* 尋找朋友正在主持之遊戲工作階段的大廳
* 為有足夠空位容納所有本機玩家的遊戲工作階段尋找大廳
* 尋找您已在其中的大廳，以便在遊戲用戶端或遊戲伺服器意外當機後復原連線。

### 支援的搜尋索引鍵

定義自訂搜尋屬性時，只允許使用一組受限的索引鍵。

* 對於字串屬性，支援下列索引鍵：string\_key1、string\_key2、\[...] string\_key30
* 對於數值屬性，支援下列索引鍵：number\_key1、number\_key2、\[...] number\_key30

### 為 FindLobbies 建構查詢字串

**FindLobbies** API 的查詢字串以類似 OData 的語法建構。篩選字串的大小上限為 600 個字元。

這些 OData 運算子可用來撰寫查詢字串。運算子會區分大小寫。

| 運算子 | 意義 | 範例 |
| - | - | - |
| eq | 等於 | string\_key1 eq 'CaptureTheFlag' |
| lt | 小於 | number\_key2 lt 10 |
| le | 小於或等於 | number\_key2 le 10 |
| gt | 大於 | number\_key3 gt 100 |
| ge | 大於或等於 | number\_key3 ge 100 |
| ne | 不等於 | string\_key1 ne 'CaptureTheFlag' |
| and | 且 | string\_key1 eq 'CaptureTheFlag' and number\_key2 lt 10 |

<Note>
  比較字串屬性時，請務必以單引號括住比較的值。例如："string\_key1 eq **'SOME STRING VALUE'**"。數值屬性不需要括住。
</Note>

另外也有預先定義的運算子可供使用。指定時必須加上 "lobby/" 前置詞。

| 運算子 | 意義 | 範例 |
| - | - | - |
| memberCount | 大廳中的玩家數目 | lobby/memberCount eq 5 |
| maxMemberCount | 大廳中允許的最大玩家數目 | lobby/maxMemberCount gt 10 |
| memberCountRemaining | 還可以加入大廳的剩餘玩家數目 | lobby/memberCountRemaining gt 0 |
| membershipLock | 大廳的鎖定狀態，必須等於 'Unlocked' 或 'Locked' | lobby/membershipLock eq 'Unlocked' |
| amOwner | 您是擁有者的大廳，必須等於 'true' | lobby/amOwner eq 'true' |
| amMember | 您是成員的大廳，必須等於 'true' | lobby/amMember eq 'true' |
| amServer | 伺服器已加入的用戶端擁有大廳，必須等於 'true' | lobby/amServer eq 'true' |

這些常數的 SDK 定義記載於[這裡](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/constants/pflobbysearchkeys)。

### 排序

OData 樣式的字串，包含此查詢以遞增 ("asc") 或遞減 ("desc") 順序進行的排序。OrderBy 子句可用於任何搜尋數字索引鍵，或屬於數值的預先定義搜尋索引鍵。若要依最接近某個數字排序，可以使用 distance 名稱，依與指定數字搜尋索引鍵的距離排序。距離排序不能搭配遞增或遞減使用。此欄位只支援一個排序子句或一個距離子句。如果未提供排序，或指定的排序需要決勝條件，預設排序將依建立時間遞減。

| 範例 | 意義 |
| - | - |
| number\_key1 asc | 依數字搜尋索引鍵遞增排序 |
| lobby/memberCount desc | 依數字搜尋索引鍵遞減排序 |
| distance\{number\_key1 = 5} | 依與指定數字的距離排序 |
| *預設* | 依建立時間遞減排序 |

## 使用 Lobby 和 Matchmaking SDK 尋找大廳的範例

在此範例中，玩家想要尋找符合下列需求的所有大廳：

* 遊戲模式為 "DeathMatch"
* 競賽風格為 "Ranked"
* 玩家的技能等級在大廳的最低和最高技能限制之內。

此外，玩家希望結果依照下列準則排序：

* 最佳技能等級最接近玩家技能等級的大廳應排在較前面

```cpp theme={null}
static PFMultiplayerHandle g_pfmHandle = nullptr;

#define SUPPORT_XBL_CROSSPLAY

#define PFLOBBY_SEARCH_KEY_GAME_MODE "string_key1"
#define PFLOBBY_SEARCH_KEY_COMPETITION_STYLE "string_key2"
#define PFLOBBY_SEARCH_KEY_SKILL "number_key1"

#define GAME_MODE_DEATH_MATCH "DeathMatch"
#define COMPETITION_STYLE_RANKED "Ranked"

// Find lobbies based on player's search criteria.
void FindGamesWithRuntimeQuery(
    uint32_t minimumSkill,
    uint32_t maximumSkill,
    uint32_t optimalSkill)
{
    PFLobbySearchFriendsFilter friendsFilter;
    friendsFilter.includeSteamFriends = true;
#ifdef SUPPORT_XBL_CROSSPLAY
    friendsFilter.includeXboxFriendsToken = MyGame::GetLocalUserXboxToken();
#endif // SUPPORT_XBL_CROSSPLAY

    // Limit results based on friend's filter.
    PFLobbySearchConfiguration searchConfiguration = { 0 };
    searchConfiguration.friendsFilter = &friendsFilter;

    // Create filter string based on player's search parameters.
    std::string filterString;
    filterString += PFLOBBY_SEARCH_KEY_GAME_MODE + std::string(" eq ") + "'" + GAME_MODE_DEATH_MATCH + "'";
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_COMPETITION_STYLE + std::string(" eq ") + "'" + COMPETITION_STYLE_RANKED + "'";
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" ge ") + std::to_string(minimumSkill);
    filterString += " and ";
    filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" le ") + std::to_string(maximumSkill);

    // Create sort string based on player's sort preference.
    std::string sortString;
    sortString += std::string("distance{") + PFLOBBY_SEARCH_KEY_SKILL + "=" + std::to_string(optimalSkill) + "}";

    searchConfiguration.filterString = filterString.c_str();
    searchConfiguration.sortString = sortString.c_str();

    HRESULT hr = PFMultiplayerFindLobbies(g_pfmHandle, &m_localUser, &searchConfiguration, nullptr);
}

void ProcessStateChanges()
{
    while (true)
    {
        uint32_t stateChangeCount;
        const PFLobbyStateChange* const* stateChanges;
        RETURN_VOID_IF_FAILED(PFMultiplayerStartProcessingLobbyStateChanges(
            g_pfmHandle,
            &stateChangeCount,
            &stateChanges));

        for (uint32_t i = 0; i < stateChangeCount; ++i)
        {
            const PFLobbyStateChange* stateChange = stateChanges[i];
            switch (stateChange->stateChangeType)
            {
                case PFLobbyStateChangeType::FindLobbiesCompleted:
                {
                    GuiPostCurrentLobbySearchResults(
                        static_cast<const PFLobbyFindLobbiesCompletedStateChange&>(*stateChange));
                    break;
                }
                default:
                {
                    break;
                }
            }
        }

        RETURN_VOID_IF_FAILED(PFMultiplayerFinishProcessingLobbyStateChanges(
            g_pfmHandle,
            stateChangeCount,
            stateChanges));
    }
}

// Update game UI to display search results when a list of matching lobbies is returned.
void GuiPostCurrentLobbySearchResults(
    const PFLobbyFindLobbiesCompletedStateChange& stateChange)
{
    if (FAILED(stateChange.result))
    {
        GuiToastErrorAndExitScreen();
        return;
    }

    for (uint32_t i = 0; i < stateChange.searchResultCount; ++i)
    {
        const PFLobbySearchResult& searchResult = stateChange.searchResults[i];
        GuiPostLobbySearchResultRow(searchResult); // defined elsewhere
    }
}
```

## 另請參閱

* [建立可搜尋的大廳](/zh-TW/services/playfab/multiplayer/lobby/define-search-keywords)
* [加入大廳](/zh-TW/services/playfab/multiplayer/lobby/join-lobbies)
* [大廳和配對](/zh-TW/services/playfab/multiplayer/lobby/lobby-and-matchmaking)
* [大廳屬性](/zh-TW/services/playfab/multiplayer/lobby/lobby-properties)
* [建立大廳](/zh-TW/services/playfab/multiplayer/lobby/create-a-lobby)


## Related topics

- [尋找大廳](/zh-TW/services/playfab/api-references/rest/multiplayer/lobby/find-lobbies.md)
- [使用 Multiplayer SDK 將 Party 與 Lobby 整合](/zh-TW/services/playfab/multiplayer/networking/party-lobby-integration.md)
- [Multiplayer Unity 外掛程式快速入門](/zh-TW/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md)
- [從 MPSD 移至 PlayFab Multiplayer 與 MPA](/zh-TW/services/xbox-services/multiplayer/mpsd/concepts/live-mpsd-to-mlp.md)
- [大廳邀請](/zh-TW/services/playfab/multiplayer/lobby/lobby-invites.md)
