MaxPlayers

MaxPlayers

#Overview

name: MaxPlayers

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 27 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of MaxPlayers is to define the maximum number of players allowed in a game session or lobby. This variable is used across various Unreal Engine subsystems and plugins related to online multiplayer functionality.

MaxPlayers is primarily used in the following Unreal Engine subsystems and modules:

  1. Online Subsystem
  2. Lobby System
  3. Session Management
  4. Matchmaking

The value of MaxPlayers is typically set in different locations depending on the context:

  1. In game session creation functions (e.g., CreateOnlineSessionInternalOSSv1, CreateOnlineSessionInternalOSSv2)
  2. In configuration files (as indicated by the UPROPERTY(globalconfig) tag)
  3. Through command-line options when launching the game
  4. Dynamically during runtime, such as in the SetMaxPlayers function

MaxPlayers often interacts with other variables such as:

  1. NumPublicConnections and NumPrivateConnections
  2. MaxPartySize
  3. NumSpectators or MaxSpectators

Developers should be aware of the following when using MaxPlayers:

  1. Ensure consistency across different subsystems (e.g., game session, lobby, and matchmaking)
  2. Consider platform-specific limitations and requirements
  3. Update related variables (like NumPublicConnections) when modifying MaxPlayers
  4. Be mindful of performance implications when setting high values

Best practices for using MaxPlayers include:

  1. Set a reasonable default value in the game configuration
  2. Allow for runtime adjustments through server admin tools or configuration files
  3. Validate input when changing the value to ensure it’s within acceptable ranges
  4. Consider scalability and server performance when determining the maximum value
  5. Ensure proper replication of the value in multiplayer scenarios
  6. Use the variable consistently across all relevant subsystems and interfaces

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseGame.ini:67, section: [/Script/Engine.GameSession]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/Online/OnlineFramework/Source/Lobby/Private/LobbyBeaconHost.cpp:62

Scope (from outer to inner):

file
function     void ALobbyBeaconHost::SetupLobbyState

Source code excerpt:

	if (LobbyState)
	{
		LobbyState->MaxPlayers = InMaxPlayers;
	}
}

void ALobbyBeaconHost::UpdatePartyLeader(const FUniqueNetIdRepl& PartyMemberId, const FUniqueNetIdRepl& NewPartyLeaderId)
{
	if (LobbyState)

#Loc: <Workspace>/Engine/Plugins/Online/OnlineFramework/Source/Lobby/Private/LobbyBeaconState.cpp:132

Scope (from outer to inner):

file
function     ALobbyBeaconState::ALobbyBeaconState

Source code excerpt:

ALobbyBeaconState::ALobbyBeaconState(const FObjectInitializer& ObjectInitializer) :
	Super(ObjectInitializer),
	MaxPlayers(0),
	LobbyBeaconPlayerStateClass(nullptr),
	LastTickTime(0.0),
	bLobbyStarted(false),
	WaitForPlayersTimeRemaining(0.0f)
{
	bReplicates = true;

#Loc: <Workspace>/Engine/Plugins/Online/OnlineFramework/Source/Lobby/Public/LobbyBeaconState.h:267

Scope (from outer to inner):

file
class        class ALobbyBeaconState : public AInfo
function     int32 GetMaxPlayers

Source code excerpt:


    /** @return number of players total allowed in the lobby */
	int32 GetMaxPlayers() const { return MaxPlayers; }

	/**
	 * Output current state of lobby to log
	 */
	void DumpState() const;
	

#Loc: <Workspace>/Engine/Plugins/Online/OnlineFramework/Source/Lobby/Public/LobbyBeaconState.h:278

Scope (from outer to inner):

file
class        class ALobbyBeaconState : public AInfo

Source code excerpt:

	/** Total number of players allowed in the lobby */
	UPROPERTY()
	int32 MaxPlayers;

	/** Class to use for lobby beacon player states */
	UPROPERTY()
	TSubclassOf<ALobbyBeaconPlayerState> LobbyBeaconPlayerStateClass;

	/** Time that last tick occurred for calculating wait time */

#Loc: <Workspace>/Engine/Plugins/Online/OnlineServicesEOSGS/Source/Private/Online/SessionsEOSGS.cpp:350

Scope (from outer to inner):

file
namespace    UE::Online
function     TFuture<TOnlineResult<FCreateSession>> FSessionsEOSGS::CreateSessionImpl

Source code excerpt:

	
	CreateSessionModificationOptions.LocalUserId = GetProductUserIdChecked(Params.LocalAccountId);
	CreateSessionModificationOptions.MaxPlayers = Params.SessionSettings.NumMaxConnections;

	const FTCHARToUTF8 SessionIdUtf8(*Params.SessionIdOverride);
	if (SessionIdUtf8.Length())
	{
		CreateSessionModificationOptions.SessionId = SessionIdUtf8.Get();
	}

#Loc: <Workspace>/Engine/Plugins/Online/OnlineServicesEOSGS/Source/Private/Online/SessionsEOSGS.cpp:512

Scope (from outer to inner):

file
namespace    UE::Online
function     void FSessionsEOSGS::SetMaxPlayers

Source code excerpt:

	UE_EOS_CHECK_API_MISMATCH(EOS_SESSIONMODIFICATION_SETMAXPLAYERS_API_LATEST, 1);

	Options.MaxPlayers = NewMaxPlayers;

	EOS_EResult ResultCode = EOS_SessionModification_SetMaxPlayers(SessionModificationHandle, &Options);
	if (ResultCode != EOS_EResult::EOS_Success)
	{
		UE_LOG(LogOnlineServices, Warning, TEXT("[FSessionsEOSGS::SetMaxPlayers] EOS_SessionModification_SetMaxPlayers failed with result [%s]"), *LexToString(ResultCode));
	}

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemEOS/Source/OnlineSubsystemEOS/Private/OnlineSessionEOS.cpp:1296

Scope (from outer to inner):

file
function     void FOnlineSessionEOS::SetMaxPlayers

Source code excerpt:

	Options.ApiVersion = 1;
	UE_EOS_CHECK_API_MISMATCH(EOS_SESSIONMODIFICATION_SETMAXPLAYERS_API_LATEST, 1);
	Options.MaxPlayers = Session->SessionSettings.NumPrivateConnections + Session->SessionSettings.NumPublicConnections;

	UE_LOG_ONLINE_SESSION(Log, TEXT("EOS_SessionModification_SetMaxPlayers() set to (%d) for session (%s)"), Options.MaxPlayers, *Session->SessionName.ToString());

	const EOS_EResult ResultCode = EOS_SessionModification_SetMaxPlayers(SessionModHandle, &Options);
	if (ResultCode != EOS_EResult::EOS_Success)
	{
		UE_LOG_ONLINE_SESSION(Error, TEXT("EOS_SessionModification_SetMaxPlayers() failed with EOS result code (%s)"), *LexToString(ResultCode));
	}

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemEOS/Source/OnlineSubsystemEOS/Private/OnlineSessionEOS.cpp:1489

Scope (from outer to inner):

file
function     uint32 FOnlineSessionEOS::CreateEOSSession

Source code excerpt:


	FSessionCreateOptions Options(TCHAR_TO_UTF8(*Session->SessionName.ToString()));
	Options.MaxPlayers = Session->SessionSettings.NumPrivateConnections + Session->SessionSettings.NumPublicConnections;
	Options.LocalUserId = EOSSubsystem->UserManager->GetLocalProductUserId(HostingPlayerNum);
	Options.bPresenceEnabled = Session->SessionSettings.bUsesPresence;
	const auto BucketIdUtf8 = StringCast<UTF8CHAR>(*GetBucketId(Session->SessionSettings));
	Options.BucketId = (const char*)BucketIdUtf8.Get();

	EOS_EResult ResultCode = EOS_Sessions_CreateSessionModification(EOSSubsystem->SessionsHandle, &Options, &SessionModHandle);

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Classes/FindTurnBasedMatchCallbackProxy.h:50

Scope (from outer to inner):

file
class        class UFindTurnBasedMatchCallbackProxy : public UOnlineBlueprintCallProxyBase

Source code excerpt:

	// Use the platform matchmaking service (like Game Center) to find a match.
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Online|TurnBased")
	static UFindTurnBasedMatchCallbackProxy* FindTurnBasedMatch(UObject* WorldContextObject, class APlayerController* PlayerController, TScriptInterface<ITurnBasedMatchInterface> MatchActor, int32 MinPlayers, int32 MaxPlayers, int32 PlayerGroup, bool ShowExistingMatches);

	// UOnlineBlueprintCallProxyBase interface
	virtual void Activate() override;
	// End of UOnlineBlueprintCallProxyBase interface

	UTurnBasedMatchInterface* GetTurnBasedMatchInterfaceObject() { return TurnBasedMatchInterface; }

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Classes/FindTurnBasedMatchCallbackProxy.h:72

Scope (from outer to inner):

file
class        class UFindTurnBasedMatchCallbackProxy : public UOnlineBlueprintCallProxyBase

Source code excerpt:


	// Maximum number of players needed for the match if a match is created
	uint32 MaxPlayers;

	// Another matchmaking parameter that must be the same for players to matchmake together - for example, this could be the game mode (1 for deathmatch, 2 for capture the flag, etc.)
	uint32 PlayerGroup;

	// Show matches that the player is already a part of in the matchmaking interface
	bool ShowExistingMatches;

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/FindTurnBasedMatchCallbackProxy.cpp:23

Scope (from outer to inner):

file
function     UFindTurnBasedMatchCallbackProxy* UFindTurnBasedMatchCallbackProxy::FindTurnBasedMatch

Source code excerpt:

}

UFindTurnBasedMatchCallbackProxy* UFindTurnBasedMatchCallbackProxy::FindTurnBasedMatch(UObject* WorldContextObject, class APlayerController* PlayerController, TScriptInterface<ITurnBasedMatchInterface> MatchActor, int32 MinPlayers, int32 MaxPlayers, int32 PlayerGroup, bool ShowExistingMatches)
{
	UFindTurnBasedMatchCallbackProxy* Proxy = NewObject<UFindTurnBasedMatchCallbackProxy>();
	Proxy->PlayerControllerWeakPtr = PlayerController;
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->MinPlayers = MinPlayers;
	Proxy->MaxPlayers = MaxPlayers;
	Proxy->PlayerGroup = PlayerGroup;
	Proxy->ShowExistingMatches = ShowExistingMatches;
	Proxy->TurnBasedMatchInterface = (UTurnBasedMatchInterface*)MatchActor.GetObject();
	return Proxy;
}

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/OnlineSessionClient.cpp:328

Scope (from outer to inner):

file
function     void UOnlineSessionClient::SetInviteFlags

Source code excerpt:

			GameSettings->bAllowJoinViaPresence = Settings.bJoinViaPresence && !Settings.bJoinViaPresenceFriendsOnly;
			GameSettings->bAllowJoinViaPresenceFriendsOnly = Settings.bJoinViaPresenceFriendsOnly;
			GameSettings->NumPublicConnections = Settings.MaxPlayers;
			SessionInt->UpdateSession(Settings.SessionName, *GameSettings, false);
		}
	}
}

#Loc: <Workspace>/Engine/Source/Runtime/CoreOnline/Public/Online/CoreOnline.h:69

Scope: file

Source code excerpt:

	/** Current max players in this session */
	UPROPERTY()
	int32 MaxPlayers;
	/** Current max party size in this session */
	UPROPERTY()
	int32 MaxPartySize;

	FJoinabilitySettings() :
		SessionName(NAME_None),

#Loc: <Workspace>/Engine/Source/Runtime/CoreOnline/Public/Online/CoreOnline.h:80

Scope (from outer to inner):

file
function     FJoinabilitySettings

Source code excerpt:

		bJoinViaPresence(false),
		bJoinViaPresenceFriendsOnly(false),
		MaxPlayers(0),
		MaxPartySize(0)
	{
	}

	bool operator==(const FJoinabilitySettings& Other) const
	{

#Loc: <Workspace>/Engine/Source/Runtime/CoreOnline/Public/Online/CoreOnline.h:92

Scope (from outer to inner):

file
function     bool operator==

Source code excerpt:

			bJoinViaPresence == Other.bJoinViaPresence &&
			bJoinViaPresenceFriendsOnly == Other.bJoinViaPresenceFriendsOnly &&
			MaxPlayers == Other.MaxPlayers &&
			MaxPartySize == Other.MaxPartySize;
	}

	bool operator!=(const FJoinabilitySettings& Other) const
	{
		return !(FJoinabilitySettings::operator==(Other));

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/GameFramework/GameSession.h:34

Scope (from outer to inner):

file
class        class AGameSession : public AInfo

Source code excerpt:

	/** Maximum number of players allowed by this server. */
	UPROPERTY(globalconfig)
	int32 MaxPlayers;

	/** Restrictions on the largest party that can join together */
	UPROPERTY()
	int32 MaxPartySize;

	/** Maximum number of splitscreen players to allow from one connection */

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/GameFramework/GameSession.h:278

Scope (from outer to inner):

file
class        class AGameSession : public AInfo

Source code excerpt:

private:

	/** Override for the default value of MaxPlayers passed to InitOptions. */
	TOptional<int32> MaxPlayersOptionOverride;

	/** Override for the default value of MaxSpectators passed to InitOptions. */
	TOptional<int32> MaxSpectatorsOptionOverride;
};

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameSession.cpp:132

Scope (from outer to inner):

file
function     void AGameSession::PostReloadConfig

Source code excerpt:

		if (MaxPlayersOptionOverride.IsSet())
		{
			MaxPlayers = *MaxPlayersOptionOverride;
		}

		if (MaxSpectatorsOptionOverride.IsSet())
		{
			MaxSpectators = *MaxSpectatorsOptionOverride;
		}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameSession.cpp:155

Scope (from outer to inner):

file
function     void AGameSession::InitOptions

Source code excerpt:

	if (UGameplayStatics::HasOption(Options, TEXT("MaxPlayers")))
	{
		MaxPlayers = UGameplayStatics::GetIntOption(Options, TEXT("MaxPlayers"), MaxPlayers);
		MaxPlayersOptionOverride = MaxPlayers;
	}

	if (UGameplayStatics::HasOption(Options, TEXT("MaxSpectators")))
	{
		MaxSpectators = UGameplayStatics::GetIntOption(Options, TEXT("MaxSpectators"), MaxSpectators);
		MaxSpectatorsOptionOverride = MaxSpectators;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameSession.cpp:357

Scope (from outer to inner):

file
function     bool AGameSession::AtCapacity

Source code excerpt:

	else
	{
		const int32 MaxPlayersToUse = CVarMaxPlayersOverride.GetValueOnGameThread() > 0 ? CVarMaxPlayersOverride.GetValueOnGameThread() : MaxPlayers;

		return ( (MaxPlayersToUse>0) && (GameMode->GetNumPlayers() >= MaxPlayersToUse) );
	}
}

void AGameSession::NotifyLogout(FName InSessionName, const FUniqueNetIdRepl& UniqueId)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameSession.cpp:445

Scope (from outer to inner):

file
function     void AGameSession::DumpSessionState

Source code excerpt:

void AGameSession::DumpSessionState()
{
	UE_LOG(LogGameSession, Log, TEXT("  MaxPlayers: %i"), MaxPlayers);
	UE_LOG(LogGameSession, Log, TEXT("  MaxSpectators: %i"), MaxSpectators);

	UOnlineEngineInterface::Get()->DumpSessionState(GetWorld());
}

bool AGameSession::CanRestartGame()

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameSession.cpp:461

Scope (from outer to inner):

file
function     bool AGameSession::GetSessionJoinability

Source code excerpt:

	check(World);

	OutSettings.MaxPlayers = MaxPlayers;
	OutSettings.MaxPartySize = MaxPartySize;
	return UOnlineEngineInterface::Get()->GetSessionJoinability(World, InSessionName, OutSettings);
}

void AGameSession::UpdateSessionJoinability(FName InSessionName, bool bPublicSearchable, bool bAllowInvites, bool bJoinViaPresence, bool bJoinViaPresenceFriendsOnly)
{

#Loc: <Workspace>/Engine/Source/Runtime/EngineSettings/Classes/GameSessionSettings.h:20

Scope (from outer to inner):

file
class        class UGameSessionSettings : public UObject

Source code excerpt:

	/** Maximum number of players allowed by this server. */
	UPROPERTY(globalconfig, EditAnywhere, Category=GameSessionSettings)
	int32 MaxPlayers;

    /** Is voice enabled always or via a push to talk key binding. */
	UPROPERTY(globalconfig, EditAnywhere, Category=GameSessionSettings)
	uint32 bRequiresPushToTalk:1;
};

#Loc: <Workspace>/Projects/Lyra/Plugins/CommonUser/Source/CommonUser/Private/CommonSessionSubsystem.cpp:509

Scope (from outer to inner):

file
function     void UCommonSessionSubsystem::CreateOnlineSessionInternalOSSv1

Source code excerpt:

{
	const FName SessionName(NAME_GameSession);
	const int32 MaxPlayers = Request->GetMaxPlayers();
	const bool bIsPresence = Request->bUseLobbies; // Using lobbies implies presence

	IOnlineSubsystem* const OnlineSub = Online::GetSubsystem(GetWorld());
	check(OnlineSub);

	IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();

#Loc: <Workspace>/Projects/Lyra/Plugins/CommonUser/Source/CommonUser/Private/CommonSessionSubsystem.cpp:531

Scope (from outer to inner):

file
function     void UCommonSessionSubsystem::CreateOnlineSessionInternalOSSv1

Source code excerpt:

	if (ensure(UserId.IsValid()))
	{
		HostSettings = MakeShareable(new FCommonSession_OnlineSessionSettings(Request->OnlineMode == ECommonSessionOnlineMode::LAN, bIsPresence, MaxPlayers));
		HostSettings->bUseLobbiesIfAvailable = Request->bUseLobbies;
		HostSettings->Set(SETTING_GAMEMODE, Request->ModeNameForAdvertisement, EOnlineDataAdvertisementType::ViaOnlineService);
		HostSettings->Set(SETTING_MAPNAME, Request->GetMapName(), EOnlineDataAdvertisementType::ViaOnlineService);
		//@TODO: HostSettings->Set(SETTING_MATCHING_HOPPER, FString("TeamDeathmatch"), EOnlineDataAdvertisementType::DontAdvertise);
		HostSettings->Set(SETTING_MATCHING_TIMEOUT, 120.0f, EOnlineDataAdvertisementType::ViaOnlineService);
		HostSettings->Set(SETTING_SESSION_TEMPLATE_NAME, FString(TEXT("GameSession")), EOnlineDataAdvertisementType::DontAdvertise);

#Loc: <Workspace>/Projects/Lyra/Plugins/CommonUser/Source/CommonUser/Private/CommonSessionSubsystem.cpp:560

Scope (from outer to inner):

file
function     void UCommonSessionSubsystem::CreateOnlineSessionInternalOSSv2

Source code excerpt:


	const FName SessionName(NAME_GameSession);
	const int32 MaxPlayers = Request->GetMaxPlayers();
	const bool bIsPresence = Request->bUseLobbies; // Using lobbies implies presence

	IOnlineServicesPtr OnlineServices = GetServices(GetWorld());
	check(OnlineServices);
	ILobbiesPtr Lobbies = OnlineServices->GetLobbiesInterface();
	check(Lobbies);

#Loc: <Workspace>/Projects/Lyra/Plugins/CommonUser/Source/CommonUser/Private/CommonSessionSubsystem.cpp:581

Scope (from outer to inner):

file
function     void UCommonSessionSubsystem::CreateOnlineSessionInternalOSSv2

Source code excerpt:

	CreateParams.SchemaId = FSchemaId(TEXT("GameLobby")); // TODO: make a parameter
	CreateParams.bPresenceEnabled = true;
	CreateParams.MaxMembers = MaxPlayers;
	CreateParams.JoinPolicy = ELobbyJoinPolicy::PublicAdvertised; // TODO: Check parameters

	CreateParams.Attributes.Emplace(SETTING_GAMEMODE, Request->ModeNameForAdvertisement);
	CreateParams.Attributes.Emplace(SETTING_MAPNAME, Request->GetMapName());
	//@TODO: CreateParams.Attributes.Emplace(SETTING_MATCHING_HOPPER, FString("TeamDeathmatch"));
	CreateParams.Attributes.Emplace(SETTING_MATCHING_TIMEOUT, 120.0f);