Download

GameMode->RestartPlayer() doesn't do anything!

In my multiplayer game, calling RestartPlayer() does nothing.



void AMyCharacter::Die(AActor* killer)
{
    if (Role < ROLE_Authority || !bCanDie || !killer)
        return;

    APAGameMode* gameMode = Cast<APAGameMode>(GetWorld()->GetAuthGameMode());

    if (gameMode)
        gameMode->RestartPlayer(this->GetController());
    else
        if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("CAN'T GET GAME MODE")));
}


The DebugMessage doesn’t get printed, so the gameMode cast succeds.

But still, nothing happens when the player dies.

I also tried this shorter version



GetWorld()->GetAuthGameMode()->RestartPlayer(this->GetController());


But still nothing.

Any tip?

Thanks in advance.

What happens if you trace in to the RestartPlayer call?

You mean setting a Breakpoint on the line where RestartPlayer() is called? If that’s what you mean, I tried.

But whenever I try to step in, I just can’t.

Inthis thread a user shows the implementation of RestartPlayer(), which uses UE_LOGs when something goes wrong.

From my Output Log window, however, no error like that is shown!

Yes, did you compile the engine in Debug Editor? The fact that you are returning right away leads me to believe the character’s player controller reference has already been removed. I don’t know where ::Die() is called in your execution chain so I can’t really judge. Try this function instead:



void AMyCharacter::Die(AActor* killer)
{
        if (Role < ROLE_Authority || !bCanDie || !killer) return;

       APAGameMode* gameMode = Cast<APAGameMode>(GetWorld()->GetAuthGameMode());
       AController* myController = GetController();
       if (gameMode != nullptr && myController != nullptr)
       {
               gameMode->RestartPlayer(this->GetController());
       }
       else if (myController != nullptr)
       {
               if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("CAN'T GET GAME MODE")));
       }
       else
       {
             if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("PLAYER CONTROLLER IS MISSING")));
       }
}


I have no “Debug Editor” since I’m using UE4 from the Launcher.

I tried your if-else test, and actually the first condition is true (RestartPlayer is called!)

Debug Editor is a version of the engine you compile.

And how I enable it on VS?

Take a look at this: How to debug engine code / get symbols - UE4 AnswerHub

Or

Download and build the engine (https://github.com/EpicGames/UnrealEngine) and choose Debug Editor in Solution Config.

So I have no other option? There’s nothing I can do to make my RestartPlayer work?

Did you look into the RestartPlayer source code to see what it is supposed to do?

As the official documentation states

And that’s what I want. Respawn my player in my multiplayer game!

I think what Manoel was trying to say is you need to trace in to RestartPlayer to see why it’s not restarting. There is a lot that could be going wrong here. Are you sure restart player is being called on the server? Are you sure all of the needed vars are valid? On and on. Without tracing in to your RestartPlayer call it’s hard to just judge from a forum post what might be going wrong. As to how to enable Debug Editor, it’s a solution configuration. Just change it from Development Editor to Debug Editor.

I entered the GameModeBase.cpp and changed the function from



void AGameModeBase::RestartPlayer(AController* NewPlayer)
{    
    if (NewPlayer == nullptr || NewPlayer->IsPendingKillPending())
    {
        return;
    }

    AActor* StartSpot = FindPlayerStart(NewPlayer);

    // If a start spot wasn't found,
    if (StartSpot == nullptr)
    {
        // Check for a previously assigned spot
        if (NewPlayer->StartSpot != nullptr)
        {
            StartSpot = NewPlayer->StartSpot.Get();
            UE_LOG(LogGameMode, Warning, TEXT("RestartPlayer: Player start not found, using last start spot"));
        }    
    }

    RestartPlayerAtPlayerStart(NewPlayer, StartSpot);
}


to



void AGameModeBase::RestartPlayer(AController* NewPlayer)
{    
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Magenta, FString::Printf(TEXT("ENTERED RestartPlayer()")));

    if (NewPlayer == nullptr || NewPlayer->IsPendingKillPending())
    {
        if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Magenta, FString::Printf(TEXT("returning from RestartPlayer()")));
        return;
    }

    AActor* StartSpot = FindPlayerStart(NewPlayer);

    // If a start spot wasn't found,
    if (StartSpot == nullptr)
    {
        // Check for a previously assigned spot
        if (NewPlayer->StartSpot != nullptr)
        {
            StartSpot = NewPlayer->StartSpot.Get();
            UE_LOG(LogGameMode, Warning, TEXT("RestartPlayer: Player start not found, using last start spot"));
        }    
    }

    RestartPlayerAtPlayerStart(NewPlayer, StartSpot);
}


But even after adding those extra debug messages, NONE OF THEM gets printed!

Well, for starters, if this is a multiplayer game and your Die() function is called from TakeDamage() and you are connected to a dedicated server then the call to AddOnScreenDebugMessage() won’t work since it will be running on the server and the server doesn’t have a screen. I’d start by suggesting you make them logs not onscreen debug. Something like:



UE_LOG(LogCharacter, Warning, TEXT("Entering %s::RestartPlayer"), *GetNameSafe(this));


But you need to learn how to actually debug the code. You’ll save yourself a lot of time. Change the solution configuration to Debug Editor, recompile then re-run the game. Set a breakpoint on the call to RestartPlayer in your Die() function. Trace in and see why it’s not restarting. I can keep making minor helpful suggestions but really this isn’t something I can debug in the forums for you.

The server is not a dedicated server. Both server and client are playing in the editor and the message is displayed in none of the two.

I’m avoiding the breakpoint-debug because I do not have the Dubug Editor configuration. And as far as I have read, I need to install UE4 debug symbols which are 18 gigabytes large!

You have a


return

before even testing the gamemode. Are you sure


Role < ROLE_Authority || !bCanDie || !killer

isn’t true and that is why restart never gets called?

Yes I’m sure.

Later on in the function I printed a debug message immediately before calling RestartPlayer().
So the problem is with the function itself not doing anything!

Are you using the github version? You can’t compile changes made to the engine source code in launcher builds. Anyway, you should override that function in your own GameMode class instead of modifying the engine implementation because it works regardless of launcher/github and is much easier to maintain.

I’m using the launcher version since I didn’t want to use extra hard disk space for something I would never use (e.g. dedicated servers)

By the way I followed your suggestion, overidding RestartPlayer() in my own GameMode:



void APAGameMode::RestartPlayer(AController* NewPlayer)
{
    Super::RestartPlayer(NewPlayer);

    if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Magenta, FString::Printf(TEXT("[GameMode] CALLING RESTART_PLAYER FROM OVERRIDE")));
}


The debug message is printed, but the character just stays there

GIF: https://i.gyazo.com/1f0503a5d68d1621…6e43fa91d6.gif

P.S. The last frame is me quitting the PlayInEditor mode

**** news ****

I have overriden all the functions involved with RestartPlayer

  • void RestartPlayer(AController* NewPlayer) override;
  • void RestartPlayerAtPlayerStart(AController* NewPlayer, AActor* StartSpot) override;
  • void FinishRestartPlayer(AController* NewPlayer, const FRotator& StartRotation) override;

These functions are not returning errors or anything.

The very last step of these functions is: **K2_OnRestartPlayer **which is defined as:



    /** Implementable event called at the end of RestartPlayer */
    UFUNCTION(BlueprintImplementableEvent, Category=Game, meta = (DisplayName = "OnRestartPlayer", ScriptName = "OnRestartPlayer"))
    void K2_OnRestartPlayer(AController* NewPlayer);


I can’t debug it… I don’t know what to do…