How to get local player controller in Multiplayer

I’m doing a multiplayer game and i’m trying to get the player’s controller so that i can spawn my UMG class.

This is what happens on BeginPlay() :

AMyPlayerController* Con = Cast<AMyPlayerController>(GetController());
if (Con) {
    GLog->Log("Added HUD 2");
    Con->BuildHUD();
}

AMyPlayerController is my player controller class.

I also tried using the condition IsLocallyController before this piece of code, but apparently it’s always false.
Also tried casting the class to pawn and the getting the pawn’s controller, which didn’t work either.

How do i successfully get the player’s controller in a network?

Don’t worry about local controllers and such. Remember that PlayerControllers only truly exist on the client and do not replicate. You should do a NetMode check instead. The reason we do this is because listen servers could also be a local client, and in my experience IsLocalController is super buggy. You don’t need to use IsLocalController in this context anyway.

void AThePawnClass::BeginPlay()
{
    if (GetNetMode() != NM_DedicatedServer)
    {
        AMyPlayerController* Con = Cast<AMyPlayerController>(GetController());
        if (Con)
        {
            GLog->Log("Added HUD 2");
            Con->BuildHUD();
        }
    }
}

void AMyPlayerController::BuildHUD()
{
   UUserWidget* MyHud = CreateWidget(UMyUserWidgetClass::StaticClass, this);
   MyHud->AddToViewport();
}

Tried it and this GetNetMode() thing will come very handy :wink: but it still won’t print that log… it’s failing the casting for some reason… thanks for the help btw appreciate the help on my other post :smiley:

Did you set your controller class as the default class in your game mode?

Yes, this is what i have in my gamemode constructor:

PlayerControllerClass = AMyPlayerController::StaticClass();

I created a blueprint from the GameMode class and set that as the GameMode, also created a blueprint from the player controller class and set that as the player controller.

And to confirm you have set your custom game mode as the active game mode for that level, yes?

This line :

PlayerControllerClass = AMyPlayerController::StaticClass();

was being executed in my gamemode class, but i tried deleting it and setting the player controller class in the blueprint that i created from the gamemode.

The original code from my question is being executed on my character.

Not insulting at all :stuck_out_tongue: this is probably not working because of something i’m missing anyway…

This question will sound really insulting and I don’t mean it that way. Are you performing this line of code in the class that the PlayerController is possessing or are you trying to reference the PlayerController from another unit’s class?

So here are the outlined steps for getting a custom character and controller going. If you have followed them all I am completely baffled at what the issue could be.

  1. Create a custom game mode and assign it to your level in the World Properties panel.
  2. Assign your custom pawn character in this game mode.
  3. Assign your custom player controller in this game mode.

One of these might be happening:

  1. Your chosen DefaultPlayerController class is being overridden in your blueprint game mode.
  2. You edited the spawning code in your game mode.
  3. The controller is null on begin play (which I highly doubt).

Is the result of GetController() (without the cast) nullptr as well?

Yes, GetController returns NULL!.

As a test what happens if you call it in Tick? What does it return? If you use “Controller” instead of “GetController()” what does it return?

Apparently i’m getting this warning on the output log:

LogLevel:Warning: EnableInput on a LevelScript actor can not be specified for only one PlayerController.

Also, the GetController() returns null on beginplay, but not on tick!! O_O

Unfortunately I’ve never encountered the first error. If the Controller is null in BeginPlay but not in Tick you might need to hack loading the GUI (I do the same thing in my app for other reasons).

Add the following code:

// Actor header file
private:

    void InitializeUserInterface();

    FTimerHandle TimerHandle_InitializeUserInterface;

// Actor cpp file
void AYourActor::BeginPlay()
{
    GetWorld()->GetTimerManager().SetTimer(TimerHandle_InitializeUserInterface, this, &AYourActor::InitializeUserInterface, 0.2f, false);
}

void AYourActor::InitializeUserInterface()
{
    AYourController* YourController = Cast<AYourController>(Controller);
    if (YourController)
    {
        // Load GUI
    }
   else
   {
      GetWorld()->GetTimerManager().SetTimer(TimerHandle_InitializeUserInterface, this, &AYourActor::InitializeUserInterface, 0.2f, false);
   }  
}

Try adding

if (GetNetMode() != NM_DedicatedServer)

before the BeginPlay line of code.

I did that and it works!! Although now i’m getting an error that says “Error Only Local Player Controllers can be assigned to widgets.”…

Still won’t work :confused: but i’ll try building the hud from the HUD class instead of creating it via player controller…

Sorry I couldn’t be more helpful in this regard. You have run into some weird issues.

It’s ok thanks for the help anyway! actually adding the hud through the hud class doesn’t work the same way so i have to do it through the player controller! getting a lot of annoying issues in this project that i can’t fix :frowning:

Or this if in a static blueprint function

APlayerController * c = GEngine->GetWorld()->GetFirstPlayerController();