Announcement

Collapse
No announcement yet.

Multiplayer-Pause

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    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.

    Click image for larger version

Name:	无标题6.png
Views:	1
Size:	447.8 KB
ID:	1204917

    #2
    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.

    Comment


      #3
      Originally posted by Kyle Langley View Post
      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...

      Comment


        #4
        Originally posted by Takylucid View Post
        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]**
        Code:
            // 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]**
        Code:
        	UFUNCTION( client, reliable )
        	void RecievePauser( APlayerState *Pauser );
        **[ATCharacter.cpp]**

        Code:
            void ATCharacter::RecievePauser_Implementation( APlayerState *Pauser )
            {
            	if( Pauser )
            	{
            		PauserName = Pauser->GetName( );
            	}
            }
        Last edited by ImVawx; 01-04-2017, 02:43 PM.

        Comment


          #5
          Originally posted by Kyle Langley View Post
          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.
          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?

          Comment


            #6
            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.
            Last edited by vipeout; 01-27-2018, 11:27 AM.

            Comment

            Working...
            X