UE4.18 Steam大厅浏览器受下载区域锁定问题求助
UE4/UE5 OnlineSubsystemSteam 仅返回同下载区域大厅的问题解决思路
问题场景
使用OnlineSubsystemSteam实现大厅搜索功能时,即使调用AddRequestLobbyListDistanceFilter(k_ELobbyDistanceFilterWorldwide)设置全球范围过滤,大厅浏览器仍仅显示Steam客户端同一下载区域内的大厅,无法获取跨区域结果。
核心排查点与修复建议
1. 修复重复的Steam API调用
你提供的CreateQuery函数中两次调用了距离过滤器:
SteamMatchmakingPtr->AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter::k_ELobbyDistanceFilterWorldwide); // ... 中间代码 ... SteamMatchmakingPtr->AddRequestLobbyListDistanceFilter(k_ELobbyDistanceFilterWorldwide);
虽然两次参数一致,但Steam API的过滤器规则是最后一次调用覆盖之前的设置,重复调用可能导致逻辑混淆。建议保留其中一次调用即可。
2. 同步UE原生搜索设置
UE的OnlineSessionSearch对象自身带有DistanceFilter参数,若未显式设置,可能会覆盖你手动添加的Steam API过滤器。在触发搜索前,务必同步设置:
// 在调用FindLobbies前设置 SearchSettings->DistanceFilter = EOnlineSessionSearchDistance::Worldwide; SearchSettings->MaxSearchResults = 100; // 扩大结果数量上限,确保能返回跨区域大厅
3. 检查隐性过滤条件
排查代码中其他搜索参数是否存在隐性区域限制:
- 确认没有添加与区域/地理位置相关的数值/字符串过滤器
- 检查
SEARCH_PLAYERSLOTS等宏定义对应的过滤逻辑是否误限制了结果范围
4. 验证测试环境
- 确保跨区域存在可搜索的大厅:用不同区域的Steam账号创建测试大厅,再用目标账号搜索
- 临时修改Steam客户端下载区域,观察搜索结果是否变化(排除客户端配置干扰)
- 登录Steamworks后台,检查游戏匹配设置是否存在强制区域限制
5. 开启Steam调试日志
通过Steamworks API开启调试日志,确认过滤器参数是否正确传递:
// 在初始化Steam子系统时添加 SteamUtils()->SetOverlayNotificationPosition(k_EPositionTopRight); SteamUtils()->SetAPIDebuggingEnabled(true);
日志会输出RequestLobbyList的具体参数,可验证距离过滤器是否生效。
调整后的CreateQuery示例代码
void FOnlineAsyncTaskSteamFindLobbiesBase::CreateQuery() { check(SteamMatchmakingPtr); // 设置全球范围距离过滤(仅保留一次调用) SteamMatchmakingPtr->AddRequestLobbyListDistanceFilter(k_ELobbyDistanceFilterWorldwide); // 最大结果数过滤 if (SearchSettings->MaxSearchResults > 0) { SteamMatchmakingPtr->AddRequestLobbyListResultCountFilter(SearchSettings->MaxSearchResults); } #ifdef SEARCH_PLAYERSLOTS { int32 PlayerSlots = 0; if (SearchSettings->QuerySettings.Get(SEARCH_PLAYERSLOTS, PlayerSlots) && PlayerSlots > 0) { SteamMatchmakingPtr->AddRequestLobbyListFilterSlotsAvailable(PlayerSlots); } } #endif // 遍历处理其他搜索参数(原逻辑不变) for (FSearchParams::TConstIterator It(SearchSettings->QuerySettings.SearchParams); It; ++It) { const FName Key = It.Key(); const FOnlineSessionSearchParam& SearchParam = It.Value(); if (Key == SEARCH_DEDICATED_ONLY || Key == SETTING_MAPNAME || Key == SEARCH_EMPTY_SERVERS_ONLY || Key == SEARCH_SECURE_SERVERS_ONLY || Key == SEARCH_PRESENCE) { continue; } #ifdef SEARCH_PLAYERSLOTS if (Key == SEARCH_PLAYERSLOTS) continue; #endif FString KeyStr; if (SessionKeyToSteamKey(Key, SearchParam.Data, KeyStr)) { if (SearchParam.ComparisonOp == EOnlineComparisonOp::Near) { switch(SearchParam.Data.GetType()) { case EOnlineKeyValuePairDataType::Int32: { int32 Value; SearchParam.Data.GetValue(Value); SteamMatchmakingPtr->AddRequestLobbyListNearValueFilter(TCHAR_TO_UTF8(*KeyStr), Value); break; } default: UE_LOG_ONLINE(Warning, TEXT("Unable to set search parameter %s"), *SearchParam.ToString()); break; } } else { switch(SearchParam.Data.GetType()) { case EOnlineKeyValuePairDataType::Int32: { int32 Value; SearchParam.Data.GetValue(Value); SteamMatchmakingPtr->AddRequestLobbyListNumericalFilter(TCHAR_TO_UTF8(*KeyStr), Value, ToSteamLobbyCompareOp(SearchParam.ComparisonOp)); break; } case EOnlineKeyValuePairDataType::Float: { SteamMatchmakingPtr->AddRequestLobbyListStringFilter(TCHAR_TO_UTF8(*KeyStr), TCHAR_TO_UTF8(*SearchParam.Data.ToString()), ToSteamLobbyCompareOp(SearchParam.ComparisonOp)); break; } case EOnlineKeyValuePairDataType::String: { FString Value; SearchParam.Data.GetValue(Value); if (!Value.IsEmpty()) { SteamMatchmakingPtr->AddRequestLobbyListStringFilter(TCHAR_TO_UTF8(*KeyStr), TCHAR_TO_UTF8(*Value), ToSteamLobbyCompareOp(SearchParam.ComparisonOp)); } else { UE_LOG_ONLINE(Warning, TEXT("Empty search parameter %s: %s"), *Key.ToString(), *SearchParam.ToString()); } break; } default: UE_LOG_ONLINE(Warning, TEXT("Unable to set search parameter %s: %s"), *Key.ToString(), *SearchParam.ToString()); break; } } } else { UE_LOG_ONLINE(Warning, TEXT("Unsupported search setting %s %s of type %s"), *Key.ToString(), *SearchParam.ToString(), EOnlineComparisonOp::ToString(SearchParam.ComparisonOp)); } } }
内容的提问来源于stack exchange,提问作者Taylor
相关产品推荐
相关产品推荐

