How to avoid engine destroy the character when player leave or get disconnect

Hello.
With BP, i trying keep the character in the map (Multiplayer) if player leave or get disconnect or network error. By default PAWN get destroyer.

I suppose i must “un posses the character” but how detect the player leave or get disconnect before the engine destroy it.

ATM players join the server in spectator mode, and then spawn the player characters and posses.

I start a thread in the forum without luck, contain more information
:

All help are welcome.
Thanks.

You can detect player leave and join using those events in GameMode class:

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/AGameMode/K2_OnLogout/index.html
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/AGameMode/K2_PostLogin/index.html

In C++ you got better selection of events on each state of player joinging, you can override engine code so there possibility to do it a lot smother.

Store the last location or last checkpint of player and restore it when he is back. Problem is how you gonna track if connecting player is the old one, i’m not sure if that possible in blueprint, you need to find some unique ID, sadly onlinesubsystem blueprint bindings don’t have nessery things to use online service id for that

Also playercontroller has a function which destroys the possessed pawn, you can override it to prevent the destruction (just unpossess insted)

Sadly you can’t do that in blueprints

thanks for your answer.

I can track that easy with BP since player already have a UserID from the “web/sql login” (already done), but restore back isn’t a option, i want the character get damage if the player disconnect or leave. I not want a player disconnect when have other enemy player in front, think in something like MOBA game, apart not the case of my game but perhaps someone doing a DOTA game want give the opportunity to other players to control the coop player character. That not possible if the engine destroy the pawn on leave/network error.

When PostLogin occur i check and Pawn its already destroyed, hard to do something for save his “life” in that event. hehe

Same other events, example in Player Character when its called EndViewTarget when leave,if i un-possess the pawn nothing change, seems the kill orderits already sent by the server.

When user leave/disconnect a “event unposses” already its called on the player character. Seems the engine before kill unposses the character but again the kill order its already sent by the server.

Perhaps my only alternative its C++ and Override that function. I will consider and check if that function avoid server destroy the pawn or do a exact a copy and spawn on kill (dirty trick alternative), but i think the engine must have a easy option for not auto destroy the posses pawn in a MP environment, or a event called before server send the “destroy pawn” for un possed the pawn. Seems a basic option for a lot of MP games.

Nope, i checked the source PawnLeavingGame is called direcly on player controller destruction (which happens when player leave).

void APlayerController::PawnLeavingGame()
{
	if (GetPawn() != NULL)
	{
		GetPawn()->Destroy();
		SetPawn(NULL);
	}
}


void APlayerController::Destroyed()
{
	if (GetPawn() != NULL)
	{
		// Handle players leaving the game
		if (Player == NULL && Role == ROLE_Authority)
		{
			PawnLeavingGame();
		}
		else
		{
			UnPossess();
		}
	}

As you can see there is condition checking if player really left (Player == NULL) and check if code runs on server (Role == ROLE_Authority), if player (the UPlayer object) still on server or playercontroller is not on server (which always will be) then it will unpossess insted.

something its not right, other thing must occur in other part of code, with this code, if player controller kill the pawn on destroy i could do anything for save his life hehe

Check the server log capture, that mean override PawLeaveGame not going to work because the Paw its destroyer before.

Then try to do debug and put brake point and then see call stack whio is calling that function

In your pawn class, override the AActor::BeginDestroy() function; I believe it’s easier this way;
You can add your game conditions there and only allow the pawn to be destroyed if you really want to, no matter where the call to Destroy() has come from.

Default destruction is

void BeginDestroy()
{
	UnregisterAllComponents();
	Super::BeginDestroy();
}

You can change it to something like

void BeginDestroy()
{
	if ( 'IReallyWantToDestroyYouBecauseGameWillEnd' ) {
 		UnregisterAllComponents();
		Super::BeginDestroy();
	} else {
		//I just gonna move you sir to base or leave your there nill or let AI play.
	}
}

ATM seems the best and easy idea . thanks. I try that this night or tomorrow.

Not luck, hehe sh*t, if i override and do any condition for destroy i got that

[2016.01.29-00.43.15:567][ 0]LogWindows:Error: Windows GetLastError: La operación se completó correctamente. (0)
[2016.01.29-00.43.15:702][ 0]LogWindows:Error: === Critical error: ===
Fatal error: [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.10\Engine\Source\Runtime\CoreUObject\Private\UObject\Obj.cpp] [Line: 662]
REINST_ThirdPersonCharacter_C_13 /Engine/Transient.TRASH_Default__ThirdPersonCharacter_C_0 failed to route BeginDestroy

, is there any way to replace player controller with AIController(in c++ or in blueprints)? I mean if human leaves or disconnects then we just put AI instead and AI controls pawn in future.

SpawnDefaultController do that, spawn the default (AIController) and possess.

I try that too, unfortunately the kill order is given in all events after close client/leave/network error i try, the early its EndViewTarget if i remember right.

I check and the player character its possessed by the AIController, but its destroyed anyway.

That a good idea if exist any other event called before the engine do the kill pawn order and was one of my first try :frowning:

Pretty weird!
I’ve done this in my test character and it worked for me when calling the Destroy Actor node:

.h:

    	virtual void K2_DestroyActor() override;

.cpp:

AIHWMTGCharacter::AIHWMTGCharacter() {
    	bAutoDestroyWhenFinished = false;
    }
    
    
    void AIHWMTGCharacter::K2_DestroyActor() {
    	if (bAutoDestroyWhenFinished) {
    		Destroy();
    	} else {
    		UnMark(OBJECTMARK_NOMARKS); ClearFlags(RF_PendingKill);
    		Reset(); ResetPropertiesForConstruction(); RerunConstructionScripts();
    		UE_LOG(LogTemp,Warning,TEXT("NOPE! I ain't gonna die..."));
    	}
    }

If APlayerController is calling usual destroy functions, something like should work too when player disconnects.

76439-ue4destroyoverride.png

I try that code, and compile but not work.
DestroyActor isn’t called neither when Quit, Close Window, (suppose but not test Network error its the same)

There are curious thing… there are a node “is actor behind Destroyed” (true/false), i use it on “Event unpossesed” and seems occur two things, the actor on that moment isn’t behind destroyed and the engine not forgive kill it at all cost few times despite assign a new controller!

i

AGameMode::K2_OnLogout() is called from within c++ AGameMode::Logout() method, where pawn is already dead

Shouldn’t happen; Epic assumes pawn must be destroyed no matter what, so the GameMode classes and code you’ll have to check to see what else is killing the pawn when unpossessed, since you said that changing PawnLeavingGame() also didn’t work.
There’s something calling Destroy() directly.

i going to check again PawnLeavingGame, i think perhaps i doing something wrong last night (lack of sleep) and its the only thing i not check hundred times and not sure if i do any stupid error.

Rethink and looking the logs , the Player Controller/PawnLeavingGame must be the guilty of kill my pawn again and again but i not understand if i give another controller the old player controller still trying kill the pawn. PlayerController->OnDestroy (GetPawn) must return NULL since i change the to the default PC :confused:

well my first test seems override PawnLeavingGame for avoid the pawn get destroyed works, i think the first time i check when comment that possibility and since my project its mainly BP, i forgive reparent “MyPlayerController” BP with the new PlayerController C++ class with that function override. That a bit embarrassing :frowning:

I will check better next days and post something but i think that problem its fixed although i want a BP only solution sometimes use C++ its mandatory, and this seems the case.

2 Likes