[BP] PlayerState gets spawned when Player leaves

Hey there,

i hope that this is NOT a bug, but i have no idea where it comes from.

I have my Lobby setup where a Player Hosts a Game as a listen Server and Clients can connect.
This is all running well. My PlayerState tells GameState on joining (BeginPlay), that he wants to be added to one of Team Arrays. Also working.

This is only place where i call function to add Player to a team!

Now, when i leave lobby by either closing game, going back to main menu or kicking player, Player tells Server to get rid of him (deleting him from arrays). Also working.

BUT THEN a new PlayerState gets spawned ON SERVER SIDE although player left.

How do i know this? Because function gets called although no new PlayerState should be created.
one of leaving player got destroyed (variables were reseted and player vanished from list).

But then from no where, server spawns a fresh PlayerState, and PState adds himself to array (BeginPlay like i said) and i have a ghost Player.

Is this normal? When i rejoin and look into scene outliner, i have more and more PlayerStates. PlayerArray of GameState shows correct amount of PlayerStates, but in debuggin area of Blueprint etc, i can clearly see another PlayerState. And this happens for every extra client that connects and leaves.

Weird thing is. If i reconnect, PlayerState does not remain in lobby. I only got clients one then.

:frowning: I have no idea if i can recreate this in a fresh project an it is already 01:39 in germany. I will get some sleep and try this tomorrow. Otherwise i would love to send one of Staff people my project in private to have a look at it.

1 Like

It is version 4.7.5 BP only and downloaded from Launcher.

I will take work around to check if Owner of PlayerState is NULL when BeginPlay tries to add PState to Arrays. Seems to work, because this weird extra PlayerState doesn’t event have an Owner…

PS: It gets spawned with a lifetime of 300sec when i click on it in Outliner. Maybe that helps you to find the “issue”.

Hi eXi,

I’m looking into this now, but if you’re able to send me a project to look at, that may speed things up for me. You can send me a download link via forums, if you’d like:

Either way, I’ll let you know what I find. Thanks for report!

Hey , thanks for time. I was already sleeping (past 0:00 in germany) and i guess now you are sleeping.

I will try to recreate this in a new project. If i am not able to, i will send you my project and a hopefully short instruction on what you need to do to see PlayerState thingy.

Ok yeah, this is easily reproducalbe in a fresh Project an it seems like this is meant to be.

I will upload fresh project i made here: https://.com/open?id=0B34nzTE-VVazRlZTaW9oSU5LaW8&authuser=0

Instructions: When you open Project, you should be in MainMenu Map. If not, look into Maps folder.

In Blueprint folder, you will find a LobbyBlueprint and a MainMenuBlueprint Folder. Inside of MainMenu folder, there is a GameMode and a PlayerController (so we can start game etc). Inside Lobby folder, there is a GameMode, PlayerController und PlayerState.

Now start game with 2 Players, but NO dedicated server. Make sure to start game in Editor window (this appears in standalone too i guess) so you can see Outliner.

Then start server on Editor Window (one INSIDE Editor is server by default) by pressing “C”.
I added Logs so you can see what happens. Then, go to Window with Client game and press “F” to find sessions. What a few seconds till Log appears and says that search was ok. Then press “J” to join found session.

When creating game, Outliner should show ONE PlayerState. When joining Game as client, Outliner should have TWO PlayerStates. All ok by now.

In CLIENT window, press “E” to leave Game and destroy session. Now PlayerState gets deleted BUT, Server creates a new second one, which has a lifetime of 300 sec.

I added a Log Print for PlayerState, so that you can see which PlayerState is calling BeginPlay.

Also PlayerState that gets created after Client leaves, will remain on Server even if Player Reconnects.This is where my Game gets a problem. I need PlayerState to fire BeginPlay when Client connects and not after he left. created PlayerState (watch Number of new one when player disconnects) will NOT fire BeginPlay again. Only when Player leaves. And since i use Begin Play to add
players to a list, this is really bad for me ):

Just try to disconnect (E), and reconnect a few times with client. You will see that PlayerState remains for him to reconnect.

I guess this is just something unreal intern, that server leaves a PlayerStates for point when Player might reconnect. Is it possible to stop this from happening? A bool or something that i can set so that Server doesn’t do this? Or do i need to kill him by hand? PlayerState has no owner, so i could call “destroy” in begin play if he has no owner, but i don’t like work arounds.

I also noticed that at least client calls BeginPlay again, maybe i will do a Client to Server call.

1 Like

Hey , we nearly hit 4 days, so i’m gonna bump this question by if you had time to look at it (: Got my “work around” (which is actualy only using client side of PlayerState) doing this by now, but i would be interested in more information about this.

Hey eXi,

Sorry for delay, I was out yesterday.

So I spoke with network team, and they said this is intentional. As you noted, if same Client reconnects with Server, PlayerState copy that was created when Client left is reacquired by Client.

There doesn’t seem to be an .ini setting for this, but you can certainly disable it in code if you’d like.

In GameMode class:

  • InactivePlayerStateLifeSpan - config time value
  • AddInactivePlayer() (and yes it does duplicate there, so there is your copy) FindInactivePlayer()

In GameState class:

  • InactivePlayerArray

All initiated from:

  • APlayerController::CleanupPlayerState()

Hope that helps!

1 Like

Awesome !

I will save this information. Would it be possible for you to speak to doc team so that they add this information? I think this is pretty important to know!

And yes it helps a lot, thank you sir.

I definitely will =)

To summarize, when a player leaves the server, the Game Mode creates a duplicate Player State which it saves to an array called ‘InactivePlayerArray’. The life span of the duplicate Player State is set to what is set in the Game Mode’s 'InactivePlayerStateLifeSpan’ variable (300 seconds by default) after which the duplicate Player State is destroyed.

A duplicate Player State is not created for players who are spectators.

It is also important to note that the Game Mode has a variable called ‘MaxInactivePlayers’. If the number of duplicate player states in the ‘InactivePlayerArray’ exceeds that number, the last (oldest) duplicate player state will be destroyed (and removed from the array) so that the newest duplicate can be added to it.

If you want to stop the Game Mode from creating the duplicate Player State, you will first need to create a C++ base class of your Game Mode and then overwrite the AddInactivePlayer function with a function that does nothing. Here’s an example:

MyGameMode.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "MyGameMode.generated.h"

/**
 * 
 */
UCLASS()
class MYGAMEMODE_API AMyGameMode : public AGameMode
{
	GENERATED_BODY()

public:

	AMyGameMode();
	virtual ~AMyGameMode() = default;

// Overwrite AddInactivePlayer function so that a duplicate player state is not created when a player disconnects from the server.

	virtual void AddInactivePlayer(APlayerState* PlayerState, APlayerController* PC) override;

};

MyGameMode.cpp

#include "MyGameMode.h"
#include "MyGameMode.h"


AMyGameMode::AMyGameMode()
{
	GameStateClass = AMyGameStyate::StaticClass();
}

void AMyGameMode::AddInactivePlayer(APlayerState* PlayerState, APlayerController* PC)
{
	// This function now does nothing instead of creating a duplicate player state and adding it to the InactivePlayerArray array as it does by default.
}

I’d like to note that the InactivePlayerArray is used for rejoins incase a player loses connection and returns. The GM uses this to correctly assign the controller to the proper character and player state.

By loses connection do you mean that they completely disconnect from the server (get kicked to the main menu) and reconnect or a temporary loss of connection e.g. for 2 seconds but the player is never kicked from the server?

Complete loss of connection to server via connection timeout, Game / OS crash etc.

Oh, in that case it doesn’t matter. The player state can be not saved if needed and won’t have any adverse effects on anything. :wink: