集成
1. 设置匹配配置
1.1 创建规则集
使用 PGOS 网页控制台管理匹配规则集。 按照以下步骤创建规则集:
- 导航至
对战/匹配
页面,点击规则集
标签页。 - 点击
添加规则集
按钮,或从现有规则集克隆
。 - 填写规则集详情。
- 规则集名称:创建一个有意义的名称,以便您在列表中轻松识别。规则集名称在游戏区服中必须唯一,后续创建匹配配置时将会使用。
- 描述:(可选)规则集的描述。
- 脚本:输入规则集主体的 JSON 文本。
验证
脚本然后提交
规则集。- 如果规则集尚未完成,可以
保存为草稿
。
加快规则集脚本编写: 规则集脚本是一个 JSON 结构,主要由四个部分组成:玩家属性、队伍、规则和扩展。
删除规则集:
- 您必须确保当前规则集没有关联的匹配配置。否则,将出现错误提示,删除操作将失败。在这种情况下,您必须更改匹配配置并使用其他规则集,然后才能删除该规则集。
- 在规则集控制台页面,选择一个规则集并点击"删除规则集"。
1.2 创建DS Placer (可选)
Placer用于确定运行战斗会话最佳Fleet 。使用现有Placer或创建新的 Placer 进行匹配 。单击“创建Placer链接了解更多详细信息:
- 创建Placer 当使用匹配作为独立服务时,可以跳过此步骤。
1.3 创建比赛配置
使用 PGOS [网页门户控制台](https://pgos.intlgame.com/#/console )来管理比赛配置。在创建比赛配置之前,您必须创建要与配置一起使用的规则集和 Placer 。 **请按照以下步骤创建比赛配置:
导航到
战斗/ 匹配
页面,然后单击比赛配置
选项卡。单击
添加比赛配置
按钮,或从现有按钮克隆
。填写比赛配置详细信息。
名称。创建一个有意义的比赛配置名称,以便您可以在列表中轻松识别它。比赛配置名称在游戏区服内必须是唯一的。 匹配请求通过其名称和区域识别要使用的比赛配置。
说明。(可选)添加比赛配置的描述。
规则集和Placer :
- 规则集:为此比赛配置选择一个规则集。
- Placer:为上面的规则集选择一个Placer 。
:::tip
您可以设置多个规则集- Placer对来实现多模式匹配 。需要注意的是,只有具有完全相同玩家属性部分的规则集才可用于匹配配置的多规则集。我们的匹配引擎是一个以规则集为导向的时间共享系统,其中每个配置的规则集均等地共享引擎的工作时间片。
对于玩家来说,通过多规则匹配获得的战斗会话将满足至少一个规则集。游戏可以使用此功能将多种游戏模式聚合到单个匹配配置中,从而提高玩家的匹配成功率。 :::
接受。 (可选)指示是否要求每个玩家在提议的对战中主动接受参与。如果选择是,请指定您希望匹配服务等待玩家接受的时长。
- 接受超时。 输入匹配服务等待所有匹配玩家接受提议对战的最长时间(以秒为单位)。取值范围为[1, 300],默认值为30。
- 自动继续。 当开启"自动继续"选项时,如果有玩家拒绝对战提议,其他所有玩家的匹配请求将返回到搜索阶段。请注意,每当匹配请求进入搜索阶段时,搜索超时时间都会重置。
准备超时。 (可选)输入匹配服务等待所有匹配玩家确认匹配结果的最长时间(以秒为单位)。 默认值为30。零表示无超时限制。我们建议使用适当的值以获得更好的匹配体验,而不是使用0。
搜索超时。 (可选)输入匹配服务为符合规则集标准的玩家进行匹配的最长时间(以秒为单位)。 默认值为30。零表示无超时限制。我们建议使用适当的值以获得更好的匹配体验,而不是使用0。
对战属性。 (可选)当通过匹配创建新的对战会话时,对战属性将传递给您的游戏服务器。
匹配配置与匹配规则集的关系: 规则集用于定义比赛的队伍结构和匹配规则,而匹配配置则引用规则集。 匹配配置用于调整与匹配流程相关的参数,例如每个阶段的超时时长、匹配成功后是否需要确认、通过 Placer 进行的匹配放置等。 当启用多规则集功能时,一个匹配配置可以关联多个共享相同玩家属性定义的规则集。 在匹配池中的玩家可以组成的多个规则集中,PGOS 将随机选择一个规则集来生成匹配。PGOS 支持为每个规则集关联特定的 Placer 以实现多模式匹配。
2. 在游戏客户端中集成匹配
以下代码以 UE4 插件的 C++ 接口为例。
2.1 准备工作
要为您的客户端准备匹配功能,请执行以下操作:
- 获取您计划使用的匹配配置的名称。
- 您还需要获取规则集中定义的必需玩家属性列表。
2.2 发起匹配请求
发起匹配请求时,您可以选择指定请求中玩家的队伍、属性和延迟信息。支持单人和组队匹配请求。
StartMatchmaking_V2
支持匹配互斥类型,匹配互斥类型的枚举值包括:
EClientMatchmakingMutexType::PerMatchmakingConfig
:对玩家可以加入的对战会话数量没有限制。同一玩家在同一匹配配置中不允许同时发起多个匹配请求。EClientMatchmakingMutexType::PerPlayer
:如果玩家有任何正在进行的对战会话或匹配,则无法发起新的匹配请求。
从匹配模块中调用 StartMatchmaking
的方式如下:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::StartMatchmaking()
{
FString ConfigurationName;
TArray<FClientMatchmakingPlayerInfo> PlayerInfoArray;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
FClientStartMatchmakingParams params;
matchmaking->StartMatchmaking_V2(params, [](const FPgosResult& Ret, const FClientStartMatchmakingInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnStartMatchmakingSuccess"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnStartMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::StartMatchmaking()
{
FClientStartMatchmakingParams params;
PGOS_CALL_ASYNC_API(UPgosClientAPIStartMatchmaking::StartMatchmaking,
this,
&SomeUObjectClass::OnStartMatchmakingSuccess,
&SomeUObjectClass::OnStartMatchmakingFailed,
params);
}
void SomeUObjectClass::OnStartMatchmakingSuccess(
FPgosResult Error, FClientStartMatchmakingInfo StartInfo)
{
UE_LOG(LogTemp, Log, TEXT("OnStartMatchmakingSuccess"))
}
void SomeUObjectClass::OnStartMatchmakingFailed(
FPgosResult Error, FClientStartMatchmakingInfo StartInfo)
{
UE_LOG(LogTemp, Log, TEXT("OnStartMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
Key Error Codes
2.3 追踪匹配请求状态
在客户端服务中添加代码以追踪所有匹配请求的状态。有两种追踪状态的方法:事件分发器和持续轮询。
Event Dispatcher
按如下方式将动态委托绑定到OnMatchmakingProcessChanged
:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->OnMatchmakingProcessChanged().AddUObject(
this,
&SomeUObjectClass::OnMatchmakingProcessChanged);
}
}
void SomeUObjectClass::OnMatchmakingProcessChanged(const FClientMatchmakingProcessChangedEvt& Event)
{
UE_LOG(LogTemp, Log, TEXT("OnMatchmakingProcessChanged"));
}
#include "PgosClientEventDispatcher.h"
void SomeUObjectClass::SomeFunction()
{
auto Dispatcher = UPgosClientEventDispatcher::GetPgosClientEventDispatcher();
if (Dispatcher)
{
Dispatcher->OnMatchmakingProcessChanged.AddDynamic(
this,
&APluginTestGameModeBase::OnMatchmakingProcessChanged);
}
}
void SomeUObjectClass::OnMatchmakingProcessChanged(const FClientMatchmakingProcessChangedEvt& Event)
{
UE_LOG(LogTemp, Log, TEXT("OnMatchmakingProcessChanged"));
}
持续轮询
要查询玩家正在进行的匹配请求,请使用 GetCurrentMatchmakings
接口。
您可以通过调用 DescribeMatchmaking 来查询匹配进度信息。
从 匹配 模块中调用 DescribeMatchmaking
的方式如下:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::DescribeMatchmaking()
{
FString TicketID;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->DescribeMatchmaking(TicketID, [](const FPgosResult& Ret, const FClientMatchmakingProcessInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("DescribeMatchmakingSuccess"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("DescribeMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::DescribeMatchmaking()
{
FString TicketID;
PGOS_CALL_ASYNC_API(UPgosClientAPIDescribeMatchmaking::DescribeMatchmaking,
this,
&SomeUObjectClass::DescribeMatchmakingSuccess,
&SomeUObjectClass::DescribeMatchmakingFailed,
TicketID);
}
void SomeUObjectClass::DescribeMatchmakingSuccess(
FPgosResult Error, FClientMatchmakingProcessInfo ProcessInfo)
{
UE_LOG(LogTemp, Log, TEXT("DescribeMatchmakingSuccess"))
}
void SomeUObjectClass::DescribeMatchmakingFailed(
FPgosResult Error, FClientMatchmakingProcessInfo ProcessInfo)
{
UE_LOG(LogTemp, Log, TEXT("DescribeMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
匹配请求状态
您可以通过事件数据(FClientMatchmakingProcessInfo
)中的EClientMatchmakingStatus
追踪匹配请求状态。主要状态说明如下:
- 准备中: 表示多人匹配的准备阶段。当多人匹配请求开始时,请求状态将变为
pgos_Preparing
,请求中的每个玩家都需要在preparing_timeout
时间内决定加入或拒绝匹配请求。 - 等待接受: 等待玩家接受匹配结果。
- 已完成: 新的对战会话和玩家对战会话已成功创建。当请求转为此状态时,您将在
FClientMatchmakingProcessInfo
中获得DS访问信息。 - 已取消: 匹配请求被玩家取消。
- 已超时: 匹配请求超时且未创建对战会话。
Key Error Codes
2.4 查询匹配中的并发玩家数量
有时您需要显示某个匹配配置中的并发玩家数量,我们提供了两种方式来帮助您实现这一点。
第一种方式最适合已经发起匹配请求的玩家,您可以在 FClientMatchmakingProcessInfo
中获取 concurrent_player_count
字段。但请注意,通过这种方式获取的玩家数量信息只会在匹配票据状态发生变化时更新。
另一种方式是使用我们在 FPgosMatchmakingAPI
模块中提供的 GetConcurrentMatchmakingPlayerCount
接口:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::GetConcurrentMatchmakingPlayerCount()
{
FClientGetConcurrentMatchmakingPlayerCountParams params;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->GetConcurrentMatchmakingPlayerCount(params, [](const FPgosResult& Ret, const FClientGetConcurrentMatchmakingPlayerCountResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetConcurrentMatchmakingPlayerCount Success"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetConcurrentMatchmakingPlayerCount Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::GetConcurrentMatchmakingPlayerCount()
{
FClientGetConcurrentMatchmakingPlayerCountParams params;
PGOS_CALL_ASYNC_API(UPgosClientAPIDescribeMatchmaking::GetConcurrentMatchmakingPlayerCount,
this,
&SomeUObjectClass::GetConcurrentMatchmakingPlayerCountSuccess,
&SomeUObjectClass::GetConcurrentMatchmakingPlayerCountgFailed,
params);
}
void SomeUObjectClass::GetConcurrentMatchmakingPlayerCountSuccess(
FPgosResult Error, FClientGetConcurrentMatchmakingPlayerCountResult ProcessInfo)
{
UE_LOG(LogTemp, Log, TEXT("GetConcurrentMatchmakingPlayerCountSuccess"))
}
void SomeUObjectClass::GetConcurrentMatchmakingPlayerCountgFailed(
FPgosResult Error, FClientGetConcurrentMatchmakingPlayerCountResult ProcessInfo)
{
UE_LOG(LogTemp, Log, TEXT("GetConcurrentMatchmakingPlayerCountgFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
2.5 处理多人匹配请求
如果您要发起包含多名玩家的匹配请求,需要添加代码来处理请求的准备阶段。
请求玩家确认多人匹配请求:
- 检测匹配请求的准备阶段
- 监控匹配请求以检测状态何时变更为
EClientMatchmakingStatus::Preparing
。
- 监控匹配请求以检测状态何时变更为
- 获取所有玩家的确认
- 玩家在准备阶段超时前有限定时间进行响应。可以使用
FClientMatchmakingProcessInfo::last_updated_status_time
和FClientMatchmakingProcessInfo::accepting_timeout
为玩家提供确认多人请求的计时机制。
- 玩家在准备阶段超时前有限定时间进行响应。可以使用
- 处理准备阶段失败的请求
- 当请求中的任何玩家选择拒绝请求时,多人请求将失败。
请注意,群组匹配请求中的玩家数量不应超过规则集中的团队人数限制(maxPlayers)。
JoinMatchmaking 示例代码
按照以下方式调用 匹配 模块中的 JoinMatchmaking
:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::JoinMatchmaking()
{
FString TicketID;
FClientMatchmakingPlayerInfo PlayerInfo;
FString Reason;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->JoinMatchmaking(TicketID, PlayerInfo, Reason, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("JoinMatchmakingSuccess"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("JoinMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::JoinMatchmaking()
{
FString TicketID;
FClientMatchmakingPlayerInfo PlayerInfo;
FString Reason;
PGOS_CALL_ASYNC_API(UPgosClientAPIJoinMatchmaking::JoinMatchmaking,
this,
&SomeUObjectClass::JoinMatchmakingSuccess,
&SomeUObjectClass::JoinMatchmakingFailed,
TicketID,
PlayerInfo);
}
void SomeUObjectClass::JoinMatchmakingSuccess(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("JoinMatchmakingSuccess"))
}
void SomeUObjectClass::JoinMatchmakingFailed(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("JoinMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
RejectMatchmaking 示例代码
按照以下方式调用匹配模块中的 RejectMatchmaking
:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::RejectMatchmaking()
{
FString TicketID;
FString Reason;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->RejectMatchmaking(TicketID, Reason, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchmakingSuccess"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::RejectMatchmaking()
{
FString TicketID;
FString Reason;
PGOS_CALL_ASYNC_API(UPgosClientAPIJoinMatchmaking::RejectMatchmaking,
this,
&SomeUObjectClass::RejectMatchmakingSuccess,
&SomeUObjectClass::RejectMatchmakingFailure,
TicketID,
Reason);
}
void SomeUObjectClass::RejectMatchmakingSuccess(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchmakingSuccess"))
}
void SomeUObjectClass::RejectMatchmakingFailed(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
2.6 处理玩家接受
如果您使用了启用了"需要接受"选项的对局配置,您需要添加代码来处理请求的接受阶段。
请求玩家接受提议的战斗:
检测匹配请求的接受阶段
- 监控匹配请求以检测状态何时更改为
EClientMatchmakingStatus::Accepting
。
- 监控匹配请求以检测状态何时更改为
获取所有玩家的接受
- 通知玩家有需要接受的提议战斗。玩家应该能够接受或拒绝战斗。战斗中的玩家信息可以从
FClientMatchmakingProcessInfo::matched_players
中获取。每个玩家的接受状态将立即更新,可以从FClientMatchedPlayerInfo::accepted
中获取。 - 在提议的战斗取消之前,玩家有有限的时间来做出回应。
FClientMatchmakingProcessInfo::last_updated_status_time
和FClientMatchmakingProcessInfo::accepting_timeout
可用于为玩家提供接受的计时机制。
- 通知玩家有需要接受的提议战斗。玩家应该能够接受或拒绝战斗。战斗中的玩家信息可以从
处理失败接受阶段的请求
- 当请求中的玩家拒绝加入战斗或在接受超时之前未能响应时,请求将转为“已终止”状态并且不再处理。对于有多个玩家的请求,如果票中的任何玩家不接受加入战斗,则整个请求将被终止。如果提议的战斗中的任何请求被拒绝,则该战斗将被取消。
处理自动继续请求
- 在失败接受的情况下,如果“自动继续”选项处于开启状态,则已接受的请求将返回到“正在搜索”状态而不是“已终止”。 通常,游戏不需要添加额外的代码来控制此流程更改。但是,游戏 UI 需要能够以某种方式适应这种反向状态转换。
AcceptMatchedBattle 的示例代码
从 匹配 模块调用AcceptMatchedBattle
,如下所示:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::AcceptMatchedBattle()
{
FString TicketID;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->AcceptMatchedBattle(TicketID, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("AcceptMatchedBattle Success"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("AcceptMatchedBattle Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::AcceptMatchedBattle()
{
FString TicketID;
PGOS_CALL_ASYNC_API(UPgosClientAPIAcceptMatchedBattle::AcceptMatchedBattle,
this,
&SomeUObjectClass::AcceptMatchedBattleSuccess,
&SomeUObjectClass::AcceptMatchedBattleFailed,
TicketID);
}
void SomeUObjectClass::AcceptMatchedBattleSuccess(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("AcceptMatchedBattleSuccess"))
}
void SomeUObjectClass::AcceptMatchedBattleFailed(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("AcceptMatchedBattleFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
RejectMatchedBattle 示例代码
按照以下方式调用匹配模块中的 RejectMatchedBattle
:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::RejectMatchedBattle()
{
FString TicketID;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->RejectMatchedBattle(TicketID, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchedBattle Success"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchedBattle Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::RejectMatchedBattle()
{
FString TicketID;
FString Reason;
PGOS_CALL_ASYNC_API(UPgosClientAPIRejectMatchedBattle::RejectMatchedBattle,
this,
&SomeUObjectClass::RejectMatchedBattleSuccess,
&SomeUObjectClass::RejectMatchedBattleFailure,
TicketID,
Reason);
}
void SomeUObjectClass::RejectMatchedBattleSuccess(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchedBattleSuccess"))
}
void SomeUObjectClass::RejectMatchedBattleFailure(FPgosResult Error)
{
UE_LOG(LogTemp, Log, TEXT("RejectMatchedBattleFailure: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
2.7 取消匹配
您可以通过调用 CancelMatchmaking 来取消匹配请求。
当匹配请求状态为 pgos_Placing
或 pgos_Pending
时,CancelMatchmaking
可能无法成功。
请按以下方式从 Matchmaking 模块调用 CancelMatchmaking
:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::CancelMatchmaking()
{
FString TicketID;
FString Reason;
auto matchmaking = IPgosSDKCpp::Get().GetClientMatchmakingAPI();
if (matchmaking)
{
matchmaking->CancelMatchmaking(TicketID, Reason, [](const FPgosResult& Ret, const FClientCancelMatchmakingInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("CancelMatchmakingSuccess"))
}
else
{
UE_LOG(LogTemp, Log, TEXT("CancelMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientMatchmakingAPI.h"
void SomeUObjectClass::CancelMatchmaking()
{
FString TicketID;
FString Reason;
PGOS_CALL_ASYNC_API(UPgosClientAPICancelMatchmaking::CancelMatchmaking,
this,
&SomeUObjectClass::CancelMatchmakingSuccess,
&SomeUObjectClass::CancelMatchmakingFailed,
TicketID,
Reason);
}
void SomeUObjectClass::CancelMatchmakingSuccess(
FPgosResult Error, FClientCancelMatchmakingInfo CancelInfo)
{
UE_LOG(LogTemp, Log, TEXT("CancelMatchmakingSuccess"))
}
void SomeUObjectClass::CancelMatchmakingFailed(
FPgosResult Error, FClientCancelMatchmakingInfo CancelInfo)
{
UE_LOG(LogTemp, Log, TEXT("CancelMatchmakingFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
Key Error Codes
3. 使用云函数修改匹配结果
在 PGOS 找到匹配结果但客户端尚未获取匹配结果之前,您可以使用云函数来检查、调整和修改匹配结果,这个过程称为后处理。您可以选择判断匹配结果的有效性、更改匹配结果,以及将某些匹配票据重新放入匹配队列继续匹配。 要实现这些操作,首先需要将云函数与匹配配置关联,然后按照与 PGOS 约定的协议规范处理匹配结果。在实际测试中,您可以通过匹配票据的事务日志了解云函数对匹配结果的后处理情况。
3.1 将云函数关联到匹配配置
使用 PGOS 控制台管理匹配配置。
- 进入"对战/匹配"页面,点击"匹配配置"标签页。
- 选择一个匹配配置并指定一个云函数。
3.2 在云函数中实现后处理逻辑
当 PGOS 找到匹配时,如果 MatchConfig 启用了云函数进行后处理任务,它将调用该云函数的 /pgos_matchmaking URL。
我们提供了一个用 Go 语言编写的云函数示例项目,演示了三种处理匹配结果的方法:
- 持续将所有匹配票据重新排队,直到超时。
- 将原始对战中的每个匹配票据分开,形成新的独立对战。
- 保持原始对战配置不变。 点击此处下载示例项目。
总的来说,云函数可以执行以下操作:
- 将请求中包含的匹配票据重新放入匹配队列继续匹配。
- 将一个匹配结果拆分成多个匹配结果,这些结果仍然包含请求中的匹配票据。
- 调整匹配票据中的队伍分配,将玩家从一个队伍移动到另一个队伍。
- 修改匹配票据中玩家的属性数据。
HTTP 请求和响应所需的 JSON 协议规范可以参考此处,,以下是基本说明:
Request:
├── trigger_id
├── operation: which will be `matchmaking_post_processing_data`
├── trigger_time: timestamp in milliseconds
└── data
├── battle_properties
└── battle: each battle is consisted of several tickets
└── tickets: ticket is a container of corresponding players
Response:
├── battles: battles processed by virtual server
└── requeued_tickets: tickets sent back to matchmaking queue
正如协议中解释,Battle
是由 PGOS 生成的对局,其中包含 Tickets
。Ticket
包含 Players
,Player
包含已分配的 team
和其他 attribute
信息。
云函数需要理解 HTTP 请求中 PGOS 生成的 Battle
,并根据规范在 HTTP 响应中返回其生成的 Battles
。它应该将任何不需要的ticekt设置为 RequeuedTickets
。然后 PGOS 会通知客户端 Battles
,并将 RequeuedTickets
重新排队回匹配队列,继续等待找到对局。
:::提示 在实现云函数以处理赛后请求时,请注意以下几点:
- 确保 HTTP 响应包含原始请求中的每个票据。每个票必须重新分配给新战斗或返回到匹配队列。
- 避免在每个票中添加或删除玩家。但是,您可以修改他们的队伍、属性和其他详细信息。
- 快速响应 HTTP 请求,以防止匹配票据因延迟过大而超时。
在以下情况下,PGOS 确定云函数调用有误,并尝试在超时限制内保持原始匹配结果:
- 云函数返回的 HTTP 错误代码不等于 200。
- 云函数返回的 HTTP 响应不符合 协议规范与 PGOS 达成一致。 - 来自云函数的 HTTP 响应缺少一些匹配票据,或者它包含不存在的新票据。
- 来自云函数的 HTTP 响应缺少匹配票据中的玩家,或者它包含不存在的新玩家。
:::
3.3 在网页门户检查后处理结果
由于匹配工单可能会经历多次后处理操作,您可以在网页控制台上查看匹配工单的详细信息,以及每个后处理实例的详细结果。这包括云函数返回的 HTTP 状态码、错误信息、处理结果、ExecutionID 以及调用所花费的时间等。
云函数的处理结果可以简要分为四种类型:
- Requeued(重新排队):票据被重新放回匹配队列进行重新匹配。
- Timedout(超时):票据最初匹配成功,但在云函数返回结果后超时。
- Changed(已更改):票据最初匹配成功,随后云函数调整了匹配结果。
- Unchanged(未更改):票据保持其初始结果,原因是云函数未修改原始匹配结果,或者 PGOS 判定云函数的响应无效并保持原始匹配结果。
4. 在客户端处理匹配结果
4.1 关联 Placer
一个匹配配置可以选择以下三种 Placer:
- Online Placer:创建战斗并在托管专用服务器上运行
- Local Placer:创建战斗并在本地运行,用于开发用途
- 无 Placer:PGOS 不会创建战斗
如果选择在线 Placer 或本地 Placer,系统会自动创建一个战斗会话,PGOS 会寻找一个 DS 来托管它。
当匹配请求状态变更为"已完成"时,游戏客户端可以从 FClientMatchmakingProcessInfo
获取战斗会话的 DS 地址信息。DS 地址信息包括:
- ip_address:运行战斗会话的实例的 IP 地址。
- port:运行战斗会话的实例的端口号。
- player_battle_session_id:分配给战斗会话中玩家的会话 ID。PGOS 将使用
player_battle_session_id
验证玩家与战斗会话的连接请求。
以下是 UE4 客户端的示例:
// Format the TravelURL with ip_address, port, and player_battle_session_id
FString TravelURL = FString::Printf(TEXT("%s:%s?player_battle_session_id=%s"),
*ip_address, *port, *player_battle_session_id);
// Connect to battle session
PlayerController->ClientTravel(TravelURL, ETravelType::TRAVEL_Absolute);
如果您选择不使用 Placer,整个流程将在获取匹配结果后停止。
4.2 订阅事件
当匹配系统找到匹配时,将触发一个名为 event_matchmaking_completed
的事件。该事件包含以下信息:
- Battle Session ID(战斗会话 ID):此匹配结果的唯一标识符。
- Matched Players(匹配玩家):匹配结果中的玩家列表。该列表包含玩家 ID、队伍名称、延迟数据和匹配属性信息。
- Configuration Name(配置名称):匹配配置名称。
- Battle Properties(战斗属性):与匹配配置相关的战斗属性。- 时间戳:找到匹配结果的时间戳。
您可以订阅此事件,订阅方法可以在此处找到。
5. 关键错误处理
以下是关键错误,但并非全部。对于列表中未列出的错误,错误信息应该已经指明了问题所在。如果您遇到晦涩的错误信息或任何其他严重错误,请与我们联系。
Error Code | 相关 API | 错误处理 |
---|---|---|
kBackendQueryMatchConfFailed | StartMatchmaking | 这表示匹配配置名称不存在。开发人员应当检查网页门户,确认匹配配置是否被意外删除或重命名。 |
kBackendQueryMatchRulesetFailed | StartMatchmaking | 这表示与匹配配置相关联的规则集不存在。开发人员应在网页门户上检查规则集是否被意外删除或重命名。 |
kBackendMemberAlreadyInMatchmaking | StartMatchmaking | 当玩家开始匹配时,如果已经存在包含该玩家的正在进行的匹配票据,就会发生这种情况。通常情况下,之前的匹配票据会被取消,以确保新的匹配票据能够成功创建。但在以下情况下,匹配服务会抛出此错误: 1. 多人匹配票据中的成员已经在另一个匹配票据中。 2. 多人匹配票据中的队长已经在另一个无法终止的匹配票据中。 |
kBackendPlayerNotInTicket | DescribeMatchmaking JoinMatchmaking RejectMatchmaking AcceptMatchmaking CancelMatchmaking | 这表示玩家正在操作一个不属于他的匹配票据。通常情况下,游戏正在追踪错误的匹配票据。 |
kBackendIllegalOperationWithEndedTicket | JoinMatchmaking RejectMatchmaking AcceptMatchmaking | 这表示匹配票据无法被加入/拒绝/接受,因为已经以下列状态结束: - COMPLETED - CANCELED - TIMEDOUT - TERMINATED |
kBackendPlayerInfoIllegal | StartMatchmaking | 这表示匹配请求中的队伍/玩家ID不合法。玩家ID不能为空。虽然队伍名称可以为空(表示玩家未指定要加入的队伍),但不能使用规则集中未定义的值。 |
kBackendPlayersInBattle | StartMatchmaking | 这表示匹配票据中的玩家已经在一个战斗会话中,在此期间不允许开始匹配,以确保一个玩家最多只能有一个战斗会话。游戏可以向玩家提示"您已在进行中的战斗中"这样的消息,并让玩家选择重新加入或退出该战斗。 |
kBackendPlayerNotInRequestedList | StartMatchmaking | 这表示匹配请求中缺少队长的信息。 |
kBackendPlayersRepeated | StartMatchmaking | 这表示匹配票据中包含重复的玩家。 |
kBackendTitleRegionIsClosed | StartMatchmaking | 这表示游戏区服已关闭。游戏应该向玩家显示类似"服务器正在维护中,请稍后再来"的提示信息。 |
kBackendPlayerCountExceedTeamLimit | StartMatchmaking | 这表示在群组匹配请求中,玩家数量超过了规则集中设定的队伍人数上限 |
kBackendPlayerInfoIllegal | StartMatchmaking | 这表示群组匹配请求中的玩家信息不合法,可能的原因如下: - 群组匹配中玩家的队伍选择不一致 |