Unreal Engine 5 C++ Multiplayer: Make Your Own Co-Op Game

Hi i managed to create a server and join online. but now when I have created new menus and have to enter the server name and enter the server name to join the server it does not find the server name.

now when i look at visual studio i see that MySessionName didn’t seem to be activated?

here are the codes

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”
#include “Subsystems/GameInstanceSubsystem.h”
#include “Interfaces/OnlineSessionInterface.h”
#include “OnlineSessionSettings.h”
#include “MultiplayerSessionsSubsystem.generated.h”

/**
*
*/
UCLASS()
class COOPADVENTURE_API UMultiplayerSessionsSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()

public:
UMultiplayerSessionsSubsystem();

void Initialize(FSubsystemCollectionBase& Collection) override;
void Deinitialize() override;

IOnlineSessionPtr SessionInterface;

UFUNCTION(BlueprintCallable)
void CreateServer(FString ServerName);

UFUNCTION(BlueprintCallable)
void FindServer(FString ServerName);

void OnCreateSessionComplete(FName SessionName, bool WasSuccessful);
void OnDestroySessionComplete(FName SessionName, bool WasSuccessful);
void OnFindSessionsComplete(bool WasSuccessful);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);

bool CreateServerAfterDestroy;
FString DestroyServerName;
FString ServerNameToFind;
FName MySessionName;

TSharedPtr<FOnlineSessionSearch> SessionSearch;

};

// Fill out your copyright notice in the Description page of Project Settings.

#include “MultiplayerSessionsSubsystem.h”
#include “OnlineSubsystem.h”

void PrintString(const FString& Str)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Cyan, Str);
}
}

UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem()
{
//PrintString(“MSS Constructor”);

CreateServerAfterDestroy = false;
DestroyServerName = "";
ServerNameToFind = "";
MySessionName = FName("Co-op Adventure Session Name");

}

void UMultiplayerSessionsSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
//PrintString(“MSS Initialize”);

IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
if (OnlineSubsystem)
{
	FString SubsystemName = OnlineSubsystem->GetSubsystemName().ToString();
	PrintString(SubsystemName);

	SessionInterface = OnlineSubsystem->GetSessionInterface();
	if (SessionInterface.IsValid())
	{
		SessionInterface->OnCreateSessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionsSubsystem::OnCreateSessionComplete);
		SessionInterface->OnDestroySessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionsSubsystem::OnDestroySessionComplete);
		SessionInterface->OnFindSessionsCompleteDelegates.AddUObject(this, &UMultiplayerSessionsSubsystem::OnFindSessionsComplete);
		SessionInterface->OnJoinSessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionsSubsystem::OnJoinSessionComplete);
	}
}

}

void UMultiplayerSessionsSubsystem::Deinitialize()
{
//UE_LOG(LogTemp, Warning, TEXT(“MSS Deinitialize”));
}

void UMultiplayerSessionsSubsystem::CreateServer(FString ServerName)
{
PrintString(“CreateServer”);

if (ServerName.IsEmpty())
{
	PrintString("Server name connot be empty");
	return;
}
FNamedOnlineSession *ExistingSession = SessionInterface->GetNamedSession(MySessionName);
if (ExistingSession)
{
	FString Msg = FString::Printf(TEXT("Session with name %s already exits, destroying it."), *MySessionName.ToString());
	PrintString(Msg);
	CreateServerAfterDestroy = true;
	DestroyServerName = ServerName;
	SessionInterface->DestroySession(MySessionName);
	return;
}

FOnlineSessionSettings SessionSettings;

SessionSettings.bAllowJoinInProgress = true;
SessionSettings.bIsDedicated = false;
SessionSettings.bShouldAdvertise = true;
SessionSettings.NumPublicConnections = 2;
SessionSettings.bUseLobbiesIfAvailable = true;
SessionSettings.bUsesPresence = true;
SessionSettings.bAllowJoinViaPresence = true;
bool IsLAN = false;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
	IsLAN = true;
}
SessionSettings.bIsLANMatch = IsLAN;

SessionSettings.Set(FName("SERVER_NAME"), ServerName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);

SessionInterface->CreateSession(0, MySessionName, SessionSettings);

}

void UMultiplayerSessionsSubsystem::FindServer(FString ServerName)
{
PrintString(“FindServer”);

if (ServerName.IsEmpty())
{
	PrintString("Server name cannot be empty");
		return;
}

SessionSearch = MakeShareable(new FOnlineSessionSearch());
bool IsLAN = false;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
	IsLAN = true;
}
SessionSearch->bIsLanQuery = IsLAN;
SessionSearch->MaxSearchResults = 9999;
SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);

SessionInterface->FindSessions(0, SessionSearch.ToSharedRef());

ServerNameToFind = ServerName;

}

void UMultiplayerSessionsSubsystem::OnCreateSessionComplete(FName SessionName, bool WasSuccessful)
{
PrintString(FString::Printf(TEXT(“OnCreateSessionComplete: %d”), WasSuccessful));

if (WasSuccessful)
{
	GetWorld()->ServerTravel("/Game/ThirdPerson/Maps/ThirdPersonMap?listen");
}

}

void UMultiplayerSessionsSubsystem::OnDestroySessionComplete(FName SessionName, bool WasSuccessful)
{
FString Msg = FString::Printf(TEXT(“OnDestroySessionComplete, SessionName: %s, Success: %d”), *SessionName.ToString(), WasSuccessful);
PrintString(Msg);

if (CreateServerAfterDestroy)
{
	CreateServerAfterDestroy = false;
	CreateServer(DestroyServerName);
}

}

void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool WasSuccessful)
{
if (!WasSuccessful) return;
if (ServerNameToFind.IsEmpty()) return;

TArray<FOnlineSessionSearchResult> Results = SessionSearch->SearchResults;
FOnlineSessionSearchResult* CorrectResult = 0;

if (Results.Num() > 0)
{
	FString Msg = FString::Printf(TEXT(" % d session found."), Results.Num());
	PrintString(Msg);

	for(FOnlineSessionSearchResult Result : Results)
	{
		if (Result.IsValid())
		{
			FString ServerName = "No name";
			Result.Session.SessionSettings.Get(FName("SERVER_NAME"), ServerName);

			if (ServerName.Equals(ServerNameToFind))
			{
				CorrectResult = &Result;
				FString Msg2 = FString::Printf(TEXT("Found server with name: %s"), *ServerName);
				PrintString(Msg2);
				break;
			}
		}
	}

	if (CorrectResult)
	{
		SessionInterface->JoinSession(0, MySessionName, *CorrectResult);
	}
	else
	{
		PrintString(FString::Printf(TEXT("Couldnt find server: %s"), *ServerNameToFind));
		ServerNameToFind = "";
	}
}
else
{
	PrintString("Zero Sessions found.");
}

}

void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (Result == EOnJoinSessionCompleteResult::Success)
{
FString Msg = FString::Printf(TEXT(“Successfully joined session %s”), *SessionName.ToString());
PrintString(Msg);

	FString Address = "";
	bool Success = SessionInterface->GetResolvedConnectString(MySessionName, Address);
	if (Success)
	{
		PrintString(FString::Printf(TEXT("Address: %s"), *Address));
		APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
		if (PlayerController)
		{
			PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
		}
	}
	else
	{
		PrintString("GetResolvedConnectString returned false");
	}
}
else
{
	PrintString("OnJoinSessionComplete failed");
}

}

Hi,
First, can you tell me the name of the lecture you were on. This will help.

When you enter a name in the UI Widget, this is the server name and not the session name. This session name should stay the same but the server name should be different. If it isn’t, it is possibly the Blueprint that gets the server name from the EditText Widget. I suspect you are showing the wrong widget in the widget switcher because of the Server Name you are getting.

As a test, add a text widget to them, one saying Create Server and the other saying Join a Friend - the content doesn’t matter and check to see if you are getting the right form showing.

Aside from that, compare the code against end of lecture and review the video again. It is going to be something little.

lecture (menu functionality)

Hi… now I find the server. the only thing i did was delete the join server text box widget, get text widget and the string and replaced them with the same ones as before. when I join the server the map dosent load I get a message in the prompt (LogGameMode: FindPlayerStart: PATHS NOT DEFINED or NO PLAYERSTART with positive rating)

This is caused by either the non-existence of a player start or the Player Start overlapping with Geometry in the map. Make sure you have at least one and move it in the clear and above the floor.

I realized I was logged into steam that’s why the player was not found. thanks for the help.

1 Like

Yeah, this is strange. It seems to be a new issue with 5.3. Also using nosteam from command line does help

You probably should have started a new thread for this @EddieJr_DigiArts

UE5 is plenty performant but it is designed for modern PCs. UE4 requires far lower specs, a 1060 GPU or equivalent ideally but you can get away with integrated GPU, 16GB ram (although again 8GB is about usable) and an SSD with a 1/2 decent CPU are more than fine, i7 or AMD equivalent ideally. For UE 5 you need a 2060 or higher card, ideally 3060 and ideally more Video RAM as well, more is better. 64GB Ram is recommended but 32GB is fine, and at least 2 SSDs plus ideally a 10th Gen i7 or equivalent or better, again higher spec is better so, for example, the 10700k over a 10700 would be better, or i9

I personally use 3 SSDs, one for OS, one for Engines, one for Source.

UE4 is far more tolerant of lower Spec computers and if you work with blueprint over C++, you can get away with lower. I used to achieve 120fps with UE4 quite comfortably at 4k with my 1060, but UE5 I get 60-120fps with a 3060ti depending on what is being done.

1 Like

Privacy & Terms