Maximum number of local players on one PC, can you have more than 4?

I am wanting to create a local play game for the PC and want more than 4 players. Is 4 the maximum number for local play or can I create more. I am not using split screen.

EDIT: Ok, i need to fix this comment. I just used the “Create Player” node, and it seems it is only possible to create 4 Player Controllers with this.

I don’t know if this can be changed, but i will have a look at the code tomorrow.

Sorry for the wasted comment >.<

Ok, i found the source of this 4 Player restriction, but i can’t tell you if it’s save to change this:

Inside the GamePlayStatics.cpp we have this function (available in Blueprints)

APlayerController* UGameplayStatics::CreatePlayer(UObject* WorldContextObject, int32 ControllerId, bool bSpawnPawn)
{
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	FString Error;

	ULocalPlayer* LocalPlayer = World->GetGameInstance()->CreateLocalPlayer(ControllerId, Error, bSpawnPawn);
   
	return (LocalPlayer ? LocalPlayer->PlayerController : NULL);
}

It, calls this function through the GameInstance.cpp:

ULocalPlayer* UGameInstance::CreateLocalPlayer(int32 ControllerId, FString& OutError, bool bSpawnActor)
{
	    
	const int32 MaxSplitscreenPlayers = (GetGameViewportClient() != NULL) ? GetGameViewportClient()->MaxSplitscreenPlayers : 1;

   	else if (LocalPlayers.Num() < MaxSplitscreenPlayers)
	{
		// If the controller ID is not specified then find the first available
		if (ControllerId < 0)
		{
			for (ControllerId = 0; ControllerId < MaxSplitscreenPlayers; ++ControllerId)
			{
				if (FindLocalPlayerFromControllerId( ControllerId ) == NULL)
				{
					break;
				}
			}
			check(ControllerId < MaxSplitscreenPlayers);
		}
		else if (ControllerId >= MaxSplitscreenPlayers)
		{
			UE_LOG(LogPlayerManagement, Warning, TEXT("Controller ID (%d) is unlikely to map to any physical device, so this player will not receive input"), ControllerId);
		}

		
	}
	else
	{
		OutError = FString::Printf(TEXT( "Maximum number of players (%d) already created.  Unable to create more."), MaxSplitscreenPlayers);
	}
    
	return NewPlayer;
}

I deleted some parts that aren’t interesting. If you want to see the full code, please look it up on github yourself.

It seems the 4 comes from the "MaxSplitscreenPlayers Variable that is set inside the GameViewportClient.cpp.

I can’t tell you if changing it to 5 will break something if you don’t use the splitscreen.

Maybe better wait for a Staff member to explain the 4. :smiley:

Max local player is setable in UGameViewportClient class

Problem is there no way to set it in blueprint, you need to do that in C++, by overriding UGameViewportClient ( create your own child class) and set MaxSplitscreenPlayers to whatever you want.in constructor or set it on AGameMode’s BeginPlay()

I guess it’s set to 4 by default as newest consoles support only 4 controller at once (fun fact: supported 7 :p)

gah you beat me :stuck_out_tongue:

Xbox One supports 8 controllers. So it would be nice to be able to set this in blueprint.

,Did anyone figure out if this works?

I got this to working! I’m using the Launcher version, no need to access any source code to modify any engine files.
So, in the editor, make a C++ class child of GameInstance.

The Header file should look like this:

#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"

UCLASS()
class MYLOCALGAME_API UMyGameInstance : public UGameInstance
{
	GENERATED_BODY()
	
public:
	
	UFUNCTION(BlueprintCallable)
		ULocalPlayer * RequestLocalPlayer(int32 ControllerId, FString & OutError, bool bSpawnActor);
};

While the cpp file should look like this:

#include "MyGameInstance.h"
#include "Engine/Engine.h"
#include "Engine/World.h"
#include "Engine/LocalPlayer.h"

ULocalPlayer* UMyGameInstance::RequestLocalPlayer(int32 ControllerId, FString& OutError, bool bSpawnActor)
{
	check(GetEngine()->LocalPlayerClass != NULL);

	ULocalPlayer* NewPlayer = NULL;
	int32 InsertIndex = INDEX_NONE;

	const int32 MaxSplitscreenPlayers = 5; // This is what does the trick!

	if (FindLocalPlayerFromControllerId(ControllerId) != NULL)
	{
		OutError = FString::Printf(TEXT("A local player already exists for controller ID %d,"), ControllerId);
	}
	else if (LocalPlayers.Num() < MaxSplitscreenPlayers)
	{
		// If the controller ID is not specified then find the first available
		if (ControllerId < 0)
		{
			for (ControllerId = 0; ControllerId < MaxSplitscreenPlayers; ++ControllerId)
			{
				if (FindLocalPlayerFromControllerId(ControllerId) == NULL)
				{
					break;
				}
			}
			check(ControllerId < MaxSplitscreenPlayers);
		}
		else if (ControllerId >= MaxSplitscreenPlayers)
		{
			UE_LOG(LogPlayerManagement, Warning, TEXT("Controller ID (%d) is unlikely to map to any physical device, so this player will not receive input"), ControllerId);
		}

		NewPlayer = NewObject<ULocalPlayer>(GetEngine(), GetEngine()->LocalPlayerClass);
		InsertIndex = AddLocalPlayer(NewPlayer, ControllerId);
		if (bSpawnActor && InsertIndex != INDEX_NONE && () != NULL)
		{
			if (()->GetNetMode() != NM_Client)
			{
				// server; spawn a new PlayerController immediately
				if (!NewPlayer->SpawnPlayActor("", OutError, ()))
				{
					RemoveLocalPlayer(NewPlayer);
					NewPlayer = NULL;
				}
			}
			else
			{
				// client; ask the server to let the new player join
				NewPlayer->SendSplitJoin();
			}
		}
	}
	else
	{
		OutError = FString::Printf(TEXT("Maximum number of players (%d) already created.  Unable to create more."), MaxSplitscreenPlayers);
	}

	if (OutError != TEXT(""))
	{
		UE_LOG(LogPlayerManagement, Log, TEXT("UPlayer* creation failed with error: %s"), *OutError);
	}

	return NewPlayer;
}

What I did was I made a copy of the function that creates a player. the Engine one checks for UGameViewport’s MaxSplitscreenPlayers, which is hard coded to 4.
So instead of go look for the value elswhere, my copy of the function is just set to 5.
The function is Callable from Blueprints, so then you just do this, probably from a GameMode on your 1st map.

Keep in mind you need to set MyGameInstance c++ class as your default game instance in order for it to exist in the game.

This is awesome! I dont suppose it works to create more splitscreen divisions but this opens lots of new gameplay possibilities.

nup, that’s a whole other topic. But this is UE4, you could create a custom split screen if you like.

I still cannot get 8 players to work after several days of scouring for information and trying to implement what I find.

My project is a blueprint project, and I have created other C++ blueprint nodes and functions with a custom blueprint node library with a bunch of handy functions, but cannot for the life of me, get more than 4 players working :frowning:
I created a C++ class derived from UGameViewportClient, and in it’s constructor, I set the MaxSplitscreenPlayers to 8. Nothing changes.
I also created a custom GameInstance class and used the code provided here, which seems to remove the error telling me that the controller ID is unlikely to map to any physical devices, but again, half of my controllers will not control the pawns that are spawned, only 4 players get control.

I have about 30 mini-games in my game, and the majority of them are in a gang beasts, single shared camera style, with a few with splitscreen (I made a blueprint node that lets me switch splitscreen on/off seamlessly). I’d like to have more than 4 players, as I think it’s important for online and local party games these days, more players, more chaos, more fun in some cases, plus it opens up more mini-game possibilities.

So eXi, or anybody, if you have any more specific instructions on how to get 8 player working, that’d be amazing.

Thank you in advance.

This does not work I’m afraid. It allows a 5th pawn to spawn, but doesn’t allow a 5th controller to be detected or usable.
I hope you could prove me completely wrong.

Well, you must be doing something wrong, because this is literally how I got it working in my game. You can have a million controllers if you want. The only place UE4 limits it to 4 is in UGameViewport, which I’m bypassing with the code above.

unless… by 5th controller do you mean GAMEPAD? because WINDOWS has a hard limit of 4 Xbox360 gamepads. But you can have up to 8 Xbox One gamepads on windows 10, here’s how.

Hmmm, I’m using all xbox one wireless controllers, all using the xbox one wireless bluetooth receiver. None of it is aftermarket, all microsoft.
The steps I took were:

  1. Create new thirdpersontemplate blueprint project called MYLOCALGAME.

  2. Once project loaded, create C++ class based on GameInstance called MyGameInstance and close
    down the editor.

  3. Copied the code from the first snippet you provided and placed that inside the header file.

  4. Copied the code from 2nd snippet and placed that into the cpp file.

  5. Rebuild in Visual studio 2017. No errors. Close VS2017 and open the project via launcher.

  6. In engine settings, change default game instance to MyGameInstance.

  7. Create new game mode called MyGameMode.

  8. On event BeginPlay , do exactly as your blueprint snippet does.

  9. Set level game mode to MyGameMode.

  10. Add 8 spawn point locations (I don’t think this matters much), and test. Only 4 pawns are controllable.

  11. Add extra code to game mode which adds force feedback/rumble to every controller detected. Only 4 are detected.

  12. Disable one or 2 of the working controllers and test. The engine delegates control to another of the connected controller that weren’t working to begin with.

I also tried setting maxSplitScreenPlayers to 8, but no such luck.
I tried creating a new C++ based on GameViewportClient and setting maximum limit in constructor, no luck there either.

I wonder if it has to do with the controllers all being connected wirelessly.
I’ve tested all controllers in windows, and they are all working and detected as I use them frequently for party nights and play 8 player games like gang beasts.

Out of curiosity, are your controllers all wired to the PC, or running via bluetooth/wirelessly?

Also, thank you for your quick response, it does raise questions that I am doing everything right, but something else is happening.

The microsoft page I linked you to specifies the 8 gamepads need to be connected by usb cables.
It doesn’t say how many can be connected with bluetooth, and you should go ask them about that.

My game only requieres 5 players, and i’m only using 4 gamepads, so I wouldn’t know really… But i do know for a fact my solution can create as many playerController/pawns as you want, which is the topic of this answerhub question though. At this point you should probably create a new one specific to your query.

Ah, right, yeah, all solutions seem to remove the restriction, but then UE4 doesn’t seem to know how to assign control to the extra controllers. I guess it’s not something easily solved. Or I need to test the controllers all wired, as it could be something to do with the controllers running off the Microsoft wireless receiver…I doubt it, but trial and error, trial and error haha.
I am determined to get this working, as I think more than 4 players in party games is a big feature that people want, along with online play, so would like to get it working sooner rather than later.
I’ll report back any findings.

So I found that all controllers are being created as expected, so I create a custom PlayerController blueprint that overrides the A button to output a message to see if any of the controllers work.
As expected, only the 4 that are controlling pawns actually work.

Another discovery was that when I turn on “Skip assigning gamepad to player 1”, I can control 5 pawns, the first can only be controlled via keyboard as expected…but no more than 5 can be controlled. Also if I turn split screen on, the keyboard player doesn’t get his own section of the screen. So this is perhaps why it looks like it works for you, since you have 4 controllers plus the keyboard.

I am trying to figure out what c++ class handles physical gamepad controllers…I figure it’s the PlayerController class, but I’m probably wrong.
One of these days, I’ll get to the bottom of this, in the mean time, it’s good practice for my C++ learning :slight_smile:

Ok, so upon more research, it cannot be done with more than 4 controllers using XInput.
DirectInput must be implemented to allow for more than 4 controllers.
This is why games like Gang Beasts have the option to disable XInput and use DirectInput to allow 8 players to work.

I haven’t tested, nor have the ability to test, but perhaps 2 xbox wireless receivers could be used, with 4 controllers assigned to each of them, that might work, even though the receiver supports 8 xbox one wireless controls, Xinput has a hard limit of 4 physical controllers.
The reason a keyboard player and 4 controllers works, is that a keyboard does not really on Xinput or DirectInput.

The only way to get more than 4 controllers to work, is to implement DirectInput to the engine.
I may not do it right away as mini-games are the priority right now, but this is where I will be starting:
https://msdn.microsoft.com/en-us/library/windows/desktop/ee418273(v=vs.85).aspx

There are various plugins that have been created which implements DirectInput, but that means relying on those plugins to stay up to date with newer engine versions too.

I hope anybody reading this, won’t waste time chasing after a solution that doesn’t involve XInput.

Anyone tried a plugin called Controlysis (which allows for directinput) with the method mentioned here to see if it allows for >4 local multiplayers?

I am still looking for a solution to this

I’m guessing you need a Blueprints only solution? because i answered my own post on “Feb 24 2018”, but it uses a C++ solution.