UE多人射击游戏CreateSession与JoinSession自定义房间名调试
自定义游戏会话名称功能修复方案
问题根源
- 原代码仅按Presence搜索会话,未针对自定义名称添加过滤逻辑,无法精准定位目标会话
- 使用FName存储用户输入的自定义名称,受FName命名规则限制(特殊字符/空格会被截断、大小写统一转换),易出现名称不匹配
- 缺少“输入名称→搜索对应会话→加入”的完整流程衔接
代码修改步骤
1. 重构CreateSession函数
改用FString接收自定义名称,避免FName的规则限制,同时将名称存入会话设置:
void UMultiplayerSessionsSubsystem::CreateSession(int32 NumPublicConnections, FString MatchType, FString CustomSessionName) { if (!SessionInterface.IsValid()) { return; } // 将输入名称安全转换为FName作为内部会话标识(自动处理非法字符) FName InternalSessionName = FName(*CustomSessionName); auto ExistingSession = SessionInterface->GetNamedSession(InternalSessionName); if (ExistingSession != nullptr) { SessionInterface->DestroySession(InternalSessionName); } CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate); LastSessionSettings = MakeShareable(new FOnlineSessionSettings()); LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "Null" ? true : false; LastSessionSettings->NumPublicConnections = NumPublicConnections; LastSessionSettings->bAllowJoinInProgress = true; LastSessionSettings->bAllowJoinViaPresence = true; LastSessionSettings->bUseLobbiesIfAvailable = true; LastSessionSettings->bShouldAdvertise = true; LastSessionSettings->bUsesPresence = true; LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing); // 用FString存储原始自定义名称,避免FName的规则限制 LastSessionSettings->Set(FName("CustomSessionName"), CustomSessionName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); if(!SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), InternalSessionName, *LastSessionSettings)) { SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle); MultiplayerOnCreateSessionComplete.Broadcast(false); } }
2. 修改FindSessions函数,支持按名称过滤
新增参数接收目标会话名称,添加过滤条件:
void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResult, FString TargetSessionName) { if(!SessionInterface.IsValid()) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, TEXT("OnlineSessionInterface Is not Valid")); } return; } FindSessionsCompleteDelegateHandle = SessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate); LastSessionSearch = MakeShareable(new FOnlineSessionSearch()); LastSessionSearch->MaxSearchResults = MaxSearchResult; LastSessionSearch->bIsLanQuery = IOnlineSubsystem::Get()->GetSubsystemName() == "Null" ? true : false; LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); // 添加自定义名称过滤,仅搜索匹配的会话 if(!TargetSessionName.IsEmpty()) { LastSessionSearch->QuerySettings.Set(FName("CustomSessionName"), TargetSessionName, EOnlineComparisonOp::Equals); } const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); if(!SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef())) { SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle); MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false); if(GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, TEXT("FindSessionFailed")); } } }
3. UI层流程衔接
- 给房主添加文本输入框,输入自定义名称后调用
CreateSession传入该名称 - 给加入者添加文本输入框,输入目标名称后调用
FindSessions传入该名称 - 在
MultiplayerOnFindSessionsComplete回调中,若搜索到结果,调用JoinSession加入第一个匹配的会话
额外注意事项
- 测试LAN模式时,确保设备在同一网络,关闭防火墙限制
- 若需要支持特殊字符/空格的会话名称,必须用FString存储,不要用FName
- 可在搜索结果回调中,将会话名称展示到UI列表,让用户选择加入(可选优化)
内容的提问来源于stack exchange,提问作者Paul Miller
相关产品推荐
相关产品推荐

