Multiplayer-Pause

I’m making a online multiplayer game, and I meet a problem.

I want the game to be pausable. I design the pause function like this.

One player pause the game in his playerController on server. It calls all the controllers to run pause functions.

The problem is when one pauses the game when others are moving, after resuming the game, others will keep moving as what they did before pausing without controll. If you want to controll them, you have to press the same direction key as the direction they are moving.

I have tried stopmovement, disable input, but both do not work.

Hey Takylucid,

Your “PauseAll” function needs to be called on the server. The naming, “Executes on Server” is a bit confusing. You will need to have a server function that then calls the multi-cast function. You currently are calling PauseAll from the client, which will fail to do anything.

Thankyou for reply!

But it works fine I think. All the clients are paused and pause menu pops up. I think Executes one Server means that this function will be executed on the server in “copied” controller of that player.

But the problem is if one pauses the game, on another client everything will be paused, when the game is resumed, the character controlled by that client would keep running without controll. Only if you press the same direction key as it is running, can you controll it again…

Sorry, I read your “GC Multi” class as a Multicast function. You’re using a server function. My bad! Ignore what I said earlier, it’s not relevant; what you are doing seems fine.

As for your issue, there was a bug a while back:

https://issues.unrealengine.com/issue/UE-34407

I am pretty sure the reason is that there is a timing issue with pause where pause will get called but not replicated (because the game is paused), causing some issues with either seeing the pause, or getting control after the pause. I also remember there where times where on pause, one of the clients would look like it was stuck running in one direction on the other clients, though the client controlling it would see a pause screen.

So the potential fix for this could be trying to force the replication of the “Pauser”, which is as follows [I know this is the Blueprint forum but there is no Blueprint for this, I think]

[MyGameMode.cpp]



    // Function Override
    bool MyGameMode::SetPause( APlayerController* PC, FCanUnpause CanUnpauseDelegate )
    {
    	if( Super::SetPause(PC, CanUnpauseDelegate)  )
    	{
    		for( FConstPawnIterator Iterator = GetWorld()->GetPawnIterator(); Iterator; ++Iterator )
    		{
    			ATCharacter *Character = Cast<ATCharacter>( *Iterator );
    			if( Character )
    			{
    				Character->RecievePauser( PC->PlayerState );
    			}
    		}
    		return true;
    	}
    	return false;
    }


[ATCharacter.h]



	UFUNCTION( client, reliable )
	void RecievePauser( APlayerState *Pauser );


[ATCharacter.cpp]



    void ATCharacter::RecievePauser_Implementation( APlayerState *Pauser )
    {
    	if( Pauser )
    	{
    		PauserName = Pauser->GetName( );
    	}
    }


Yes the issue exists, although I have fixed it by simply calling a multicast and setting “Pauser” property in the WorldSettings. I could not find PauserName property in character class. Problem is, for some reason the client’s controllers are receiving PostNetInit() starting all the initialization all over again, heavily messing up any logic that there was. It happens because the client receives a channel with NULL actor, so it spawns a new one.

I cannot see where the host causes this and I’d really like to avoid that. Do you maybe have some hints, as to where to look?

Ok, for anyone ever wandering into this part of internet seeking answer - I did it. You HAVE TO ASSURE that all the clients pause before the host. I did it using RPC calls (since you’re working around the pause-all-logic place, OnRep variables are unreliable and often do not get replicated at all). Goes as follows:

  1. Client asks the host to pause the game through a Server RPC (if the host is the one pausing you skip this step)
  2. Host iterates over all the client controllers calling a Client RPC with requesting pause (sending the original client who asked along in form of his player state)
  3. All clients set their “pauser” property in worldsettings and call a Server RPC with “confirmed” message (with the received player state)
  4. Host receives the confirm message, checks whether all controllers are ready, if so proceeds to pause his game

Analogous for unpause logic. I have not seen any bugs with unpause being unsynchronized, but I prefer deterministic solutions. If you plan on doing all this in PlayerController, then remember that on host there are all of them and certain data you may want to keep static (for me it was bool for “I am during all that logic, do not interrupt me and ignore all other requests for pause” and cached current pauser - player state of the one issuing the entire chain.

You could theoretically always set the pauser to be yourself on clients and never send it through the Client RPC, but then you have no data at all, and I needed some idea on who’s doing it.

It does cause minor desynchro (fixing itself upon unpause), but works very good besides that - connection is kept, timeouts are received etc. Following this logic I have not experienced any “player keeps moving in some direction” nor “player stuck”.

Interesting to note however is, that all the user input is processed, so your character can move around despite the fact that the world is paused. Block it in some way, and you’re done for the most part. I ended up adding more features (writing out who paused/unpaused the game, counting down some time to make sure others can unpause if the pauser goes AFK too long, etc.) Good luck.

Hi, it is 2021 now, and I am using UE 4.27.1 . I tried your solution, but I still face the same issue, (i.e. the clients are not paused while the server is paused; The clients’ actors will not be synchronized until the server is unpaused; I am sure the RecievePauser_Implementation is triggered on clients by using visual studio breakpoint). I know the UE has been changed a lot. How should I fix it now? Thanks.

Hello RogerQea, Hello all, I also search for a solution to pause a multiplayer game. Same problem for my, server can pause, but clients are not. Somebody knows a BP solution to pause Clients and Server?

Easier solution to all these issues is to just set global time dilation to 0.0001 instead of pausing the game. This function should be called on the server and all clients manually (multicast RPC). This node is available in BP.

1 Like

I’m still looking as well. I tried pausing just in Gamemode or casting to all Player Controllers. The mysterious thing is that all my solutions worked, but just about every second time. I can’t follwo viepouts idea, because i don’t find a “pauser” property in worldsettings.

Easier solution to all these issues is to just set global time dilation to 0.0001 instead of pausing the game. This function should be called on the server and all clients manually (multicast RPC). This node is available in BP.

Did you find any downsides or limitations when using “set global time dilation” on clients? Is it affecting the same actors/objects as doing “game pause”?

One downside I see directly. When an Actor has the option “don’t pause when game pause” (e.g. available in PlayerController) the actor will still “fake pause” when using “set global time dilation”.
Is there any way to exclude actors from “global time dilation” without doing the other way around and manually select all actors doing “time dilation to 0.0001”.

Thanks a lot!

Cloth physics behave weird. Not sure about rigid body physics.

You could set global time dilation to 0.0001 and then custom time dilation for each actor you want to 10000.

1 Like