I’ve got a working system set up that allows me to create, search for, join, and destroy listen servers. This was previously all being done on the GameInstance class. However while dissecting ShooterGame, I noticed that most of that functionality had been broken out to GameSession, with only a few functions on GameInstance to call things. This seemed odd to me given that the session class only exists as long as the session does, but nonetheless I decided to experiment and moved the necessary functions over there.
It compiles and runs fine, but as expected, I ran into a problem. Because the function that actually calls CreateSession() is on GameSession, we first need to get and cast to GameSession in order to call it. But because GameSession doesn’t exist until after CreateSession() is called, the cast returns null and the necessary functions can’t be called. This is of course a paradox, so either Epic’s code on ShooterGame is totally bonked, or (the much more likely probability) I’m missing something fundamental about how ShooterGame’s code actually works.
Can anyone offer any insight here? I’ve scoured a bunch of the other source files and I can’t for the life of me figure out how it can be accessing the session class apparently before it’s created.
Here’s a snippet of the relevant code from my own project. Once again this compiles and runs just fine, but as I expected it doesn’t ever make it inside the conditional in the first block of code. Instead it prints out the second of the two custom debug macros, indicating that the session doesn’t yet exist.
(Also please note CreateServer() is just my own implementation, not to be confused with CreateSession() - probably going to rename these)
In E6KGameInstance.cpp
void UE6KGameInstance::CreateServer(FString ServerName, bool bIsPublic)
{
AE6KGameSession* const GameSession = GetGameSession(); // NOTE: GetGameSession() casts to AE6KGameSession and then returns a pointer to it
if (GameSession)
{
PRINT_STRING(Cyan, "GAME SESSION FOUND!!!") // NOTE: Custom macro
GameSession->CreateServer(ServerName, bIsPublic);
return;
}
PRINT_STRING(Red, "NO GAME SESSION FOUND!!!") // NOTE: Custom macro
}
Which then calls:
In E6KGameSession.cpp
void AE6KGameSession::CreateServer(FString ServerName, bool bIsPublic)
{
if (!SessionInterface.IsValid()) return;
// Sets up initial settings for creating a session
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
SessionSettings = MakeShareable(new FE6KOnlineSessionSettings(ServerName, CheckForLAN(), bIsPublic));
// Creates new session
if (LocalPlayer)
{
OnCreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);
SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *SessionSettings);
}
}
*Before you reply! Once again, I understand why this code isn’t working. I want to understand how and why the equivalent classes on ShooterGame are set up similarly and yet I assume run just fine.