Hi, I’m currently prototyping a network game where we need to have several players on the same map in local.
I followed [eXi’s tutorial][1] about networking but I currently have an issue.
The first player is able to host correctly and gets into the map, but when another user tries, the find session works fine but there is no session found. If the second player joins with the command open [IP] it works fine, so the session has successfully been created but it looks like the second computer cant find it.
Here are some images of the issue :
When i host the game :
And when I then try to join :
When hosting it tells that the session has been successfully created but when I try to join it, it tells that the search has been complete but that no session has been found. I tried both in editor and once packaged in debug. I also tried on one single machine or on several computers on the same network. None of those tests had been successful.
Here are some code samples :
In DefaultEngine.ini :
[OnlineSubsystem]
DefaultPlatformService=LAN
In Arena.build.cs :
public class Arena : ModuleRules
{
public Arena(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "OnlineSubsystem", "OnlineSubsystemUtils" });
DynamicallyLoadedModuleNames.Add("OnlineSubsystemNull");
}
}
Here comes some ArenaInstance’s code sample (the game instance used in this project) :
In ArenaInstance.cpp :
The part where we host a session :
bool UArenaInstance::HostSession(TSharedPtr<const FUniqueNetId> _userID, FName _sessionName, bool _isLAN, bool _isPresence, int32 _maxPlayerAmount)
{
IOnlineSubsystem* const onlineSub = IOnlineSubsystem::Get();
if (onlineSub)
{
IOnlineSessionPtr sessions = onlineSub->GetSessionInterface();
if (sessions.IsValid() && _userID.IsValid())
{
m_sessionSettings = MakeShareable(new FOnlineSessionSettings());
m_sessionSettings->bIsLANMatch = _isLAN;
m_sessionSettings->bUsesPresence = _isPresence;
m_sessionSettings->NumPublicConnections = _maxPlayerAmount;
m_sessionSettings->NumPrivateConnections = 0;
m_sessionSettings->bAllowInvites = true;
m_sessionSettings->bAllowJoinInProgress = false;
m_sessionSettings->bShouldAdvertise = true;
m_sessionSettings->bAllowJoinViaPresence = true;
m_sessionSettings->bAllowJoinViaPresenceFriendsOnly = false;
m_sessionSettings->Set(SETTING_MAPNAME, FString("NewMap"), EOnlineDataAdvertisementType::ViaOnlineService);
OnCreateSessionCompleteHandle = sessions->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);
return sessions->CreateSession(*_userID, _sessionName, *m_sessionSettings);
}
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, TEXT("No OnlineSubsystem found"));
}
return false;
}
void UArenaInstance::OnCreateSessionComplete(FName _sessionName, bool _wasSuccessful)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("OnCreateSessionComplete %s, %d"), *_sessionName.ToString(), _wasSuccessful));
//Get the online sub so we have access to the session interface
IOnlineSubsystem* onlineSub = IOnlineSubsystem::Get();
if (onlineSub)
{
IOnlineSessionPtr sessions = onlineSub->GetSessionInterface();
if (sessions.IsValid())
{
sessions->ClearOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteHandle);
if (_wasSuccessful)
{
//Set the startsession delegate handle
OnStartSessionCompleteHandle = sessions->AddOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegate);
//The startsessioncomplete delegate should get called after this
sessions->StartSession(_sessionName);
}
}
}
}
void UArenaInstance::OnStartSessionComplete(FName _sessionName, bool _wasSuccessful)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("OnStartSessionComplete %s %d"), *_sessionName.ToString(), _wasSuccessful));
IOnlineSubsystem* onlineSub = IOnlineSubsystem::Get();
if (onlineSub)
{
IOnlineSessionPtr sessions = onlineSub->GetSessionInterface();
if (sessions.IsValid())
{
sessions->ClearOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteHandle);
}
}
if (_wasSuccessful)
{
UGameplayStatics::OpenLevel(GetWorld(), "Arena1", true, "listen?bIsLanMatch = 1");
}
}
The part where we search a session :
void UArenaInstance::FindSessions(TSharedPtr<const FUniqueNetId> _userID, bool _isLAN, bool _presence)
{
IOnlineSubsystem* onlineSub = IOnlineSubsystem::Get();
if (onlineSub)
{
IOnlineSessionPtr sessions = onlineSub->GetSessionInterface();
if (sessions.IsValid() && _userID.IsValid())
{
m_SessionSearch = MakeShareable(new FOnlineSessionSearch());
m_SessionSearch->bIsLanQuery = _isLAN;
m_SessionSearch->MaxSearchResults = 20;
m_SessionSearch->PingBucketSize = 50;
if (_presence)
{
m_SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, _presence, EOnlineComparisonOp::Equals);
}
TSharedRef<FOnlineSessionSearch> searchSettingsRef = m_SessionSearch.ToSharedRef();
OnFindSessionCompleteHandle = sessions->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionCompleteDelegate);
sessions->FindSessions(*_userID, searchSettingsRef);
}
else
{
OnFindSessionComplete(false);
}
}
else
{
OnFindSessionComplete(false);
}
}
void UArenaInstance::OnFindSessionComplete(bool _wasSuccessful)
{
if (_wasSuccessful)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("FindSessionComplete SUCCESS")));
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("FindSessionComplete FAILURE")));
}
IOnlineSubsystem* const onlineSub = IOnlineSubsystem::Get();
if (onlineSub)
{
IOnlineSessionPtr sessions = onlineSub->GetSessionInterface();
if (sessions.IsValid())
{
sessions->ClearOnFindSessionsCompleteDelegate_Handle(OnFindSessionCompleteHandle);
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("Num Search Result : %d"), m_SessionSearch->SearchResults.Num()));
for (int i = 0; i < m_SessionSearch->SearchResults.Num(); i++)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("Session Number : %d | SessionName : %s"), i+1, *(m_SessionSearch->SearchResults[i].Session.OwningUserName)));
}
}
}
}
Those functions are called in blueprint using this functions :
void UArenaInstance::StartOnlineGame(FName _sessionName)
{
ULocalPlayer* const player = GetFirstGamePlayer();
HostSession(player->GetPreferredUniqueNetId(), _sessionName, true, true, 10);
}
void UArenaInstance::FindOnlineGames()
{
ULocalPlayer* const player = GetFirstGamePlayer();
FindSessions(player->GetPreferredUniqueNetId(), true, true);
}
The blueprint calling that is on a simple UI :
If anyone had an idea how to solve that issue that would be great, thanks in advance (I’m available if you need more sources).