Unable to obtain Reference to PlayerController

I have managed to compile without errors.

This is the lecture where we made a PlayerControllerBase class, then wrote in references to this new class in the TankGameModeBase .cpp and .h files.

TankGameModeBase.h

class APlayerControllerBase; // forward declaration
private:
APlayerControllerBase* PlayerControllerRef;

.
TankGameModeBase.cpp

void ATankGameModeBase::HandleGameStart()
{
   PlayerControllerRef = Cast<APlayerControllerBase>(UGameplayStatics::GetPlayerController(this, 0));
   .
   . //rest of code not included
}

^^ The above Cast fails.
As part of troubleshooting I created the next line…

if (!PlayerControllerRef) UE_LOG(LogTemp, Error, TEXT("!PlayerControllerRef"));

And the LOG confirms that UE4 cannot make a reference to APlayerController.
Removing the Cast and simply having the APlayerControllerBase* PlayerControllerRef; declaration from the Header file gives the same result - no reference to the PlayerController.

The other casts work.
ie- PlayerTank = Cast<APawnTank>(UGameplayStatics::GetPlayerPawn(this, 0));

And I have checked the #includes and forward declarations.
As I said, everything compiles.

I’m not sure where else to look.

That would imply that the player controller isn’t using your APlayerControllerBase class. What do you have in the game mode?

The c++ Game Mode files ?
Or do you mean some other GameMode relationship ?

TankGameModeBase.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "TankGameModeBase.generated.h"

class APawnTurret;
class APawnTank;
class APlayerControllerBase;
class ATankGameModeBase;

UCLASS()
class TOONTANKS_API ATankGameModeBase : public AGameModeBase
{
	GENERATED_BODY()

private:
	APawnTank* PlayerTank;
	int32 TargetTurrets = 0;
	int32 GetTargetTurretCount();
	APlayerControllerBase* PlayerControllerRef;
	ATankGameModeBase* GameModeRef;
	void HandleGameStart();
	void HandleGameOver(bool PlayerWon);
	

public:
	void ActorDied(AActor* DeadActor);


protected:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Game Loop")
	int32 OnYourMarks = 5;

	virtual void BeginPlay() override;
	UFUNCTION(BlueprintImplementableEvent)
	void GameStart();
	UFUNCTION(BlueprintImplementableEvent)
	void GameOver(bool PlayerWon);
	
};

.
.
.
TankGameModeBase.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "ToonTanks/GameModes/TankGameModeBase.h"
#include "ToonTanks/Pawns/PawnTank.h"
#include "ToonTanks/Pawns/PawnTurret.h"
#include "Kismet/GameplayStatics.h"
#include "TimerManager.h"
#include "ToonTanks/PlayerControllers/PlayerControllerBase.h"
#include "GameFramework/Actor.h"



void ATankGameModeBase::BeginPlay()
{
    // get references and the game win/lose conditions.

    Super::BeginPlay();
    
    HandleGameStart();

    // call HandleGameStart() to initialise the start countdown, turret activation, pawn check, etc...
}




void ATankGameModeBase::ActorDied(AActor* DeadActor)
{
    // All died Actors get passed in here.
    // check what type of actor died.
    // If Turret, then tally.   If player, then go to lose condition.
    if (DeadActor == PlayerTank)
    {
        PlayerTank->ManageDestruction();
        if (PlayerControllerRef)
        {
            PlayerControllerRef->SetPlayerEnabledState(false);
        }
        HandleGameOver(false);
    }
    else if (APawnTurret* DestroyedTurret = Cast<APawnTurret>(DeadActor))
    {
        DestroyedTurret->ManageDestruction();
        --TargetTurrets;
        if (TargetTurrets <=0)
        {
            HandleGameOver(true);
        }
    }
    UE_LOG(LogTemp, Error, TEXT("DEAD SKUNK !!  void ATankGameModeBase::ActorDied(AActor* DeadActor)"));
}




int32 ATankGameModeBase::GetTargetTurretCount()
{
    TArray<AActor*> TurretActors; //OUT parameter
    UGameplayStatics::GetAllActorsOfClass(GetWorld(), APawnTurret::StaticClass(), TurretActors);
    return TurretActors.Num();
}




void ATankGameModeBase::HandleGameStart()
{
    // initialise the start countdown, turret activation, pawn check, etc...
    
    TargetTurrets = GetTargetTurretCount();

    PlayerTank = Cast<APawnTank>(UGameplayStatics::GetPlayerPawn(this, 0));

    PlayerControllerRef = Cast<APlayerControllerBase>(UGameplayStatics::GetPlayerController(this, 0));
    if (!PlayerControllerRef) UE_LOG(LogTemp, Error, TEXT("!PlayerControllerRef"));

    GameStart();

    if (PlayerControllerRef)
        {
            PlayerControllerRef->SetPlayerEnabledState(false);
            
            FTimerHandle PlayerEnableHandle;
            FTimerDelegate PlayerEnableDelegate;

            PlayerEnableDelegate = FTimerDelegate::CreateUObject(PlayerControllerRef,
                                                                 &APlayerControllerBase::SetPlayerEnabledState,
                                                                 true);

            GetWorld()->GetTimerManager().SetTimer(PlayerEnableHandle, PlayerEnableDelegate, OnYourMarks, false);
        }
    
}




void ATankGameModeBase::HandleGameOver(bool PlayerWon)
{
    // See if the player has destroyed the turrets, show in result.
    // else if turret destroyed player, show lose result.
    // call blueprint version.... GameOver(bool)
    GameOver(PlayerWon);
}

No, the settings in maps & modes

1 Like

Ahh, yes.
Thankyou.

It had to be something quick and clean like that.

Problem solved :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms