Cannot control custom pawn. Please help.

I am trying to create a pawn that is a small sphere (like the default pawn), that floats around controlled by the player (like the default pawn) but which has a built in spotlight to illuminate everything the player sees (like a miner’s helmet).

Nothing is working.

I cannot get my pawn to be anywhere but where I clicked when I first added it to the scene. It ignores all PlayerStart actors and all attempts to locate it manually. I cannot even move it in the editor. The fulcrum will move briefly, but the mesh does not.

I managed to get the control input to control the light but not the camera viewpoint, and the mesh for the default pawn was either stuck with the camera viewpoint or invisible. I currently have it so that the camera rotates with the control input, but does not move, while the light is stuck fast.

Here is my code:

#pragma once


#include "Camera/CameraComponent.h"
#include "Components/SpotLightComponent.h"
#include "GameFramework/DefaultPawn.h"
#include "DungeonEye.generated.h"


UCLASS()
class DUNGEON_EDITOR_API ADungeonEye : public ADefaultPawn
{
    GENERATED_UCLASS_BODY()

    public:

    protected:
        virtual void BeginPlay() override;

    private:
        TObjectPtr<class USpotLightComponent>  m_light;

};
#include "DungeonEye.h"


ADungeonEye::ADungeonEye(const FObjectInitializer &initialiser)
           : Super(initialiser)
{
    // Eventually we want to create these dynamically when players connect and associate them with the player
    // that just connected.
    AutoPossessPlayer = EAutoReceiveInput::Player0;
    AutoPossessAI = EAutoPossessAI::Disabled;
    BaseEyeHeight = 0.0f;
    SetCanBeDamaged(false);
    bIsEditorOnlyActor = false;

    m_light = CreateDefaultSubobject<USpotLightComponent>(TEXT("DungeonEyeLight"));
    m_light->SetupAttachment(RootComponent);
}


void ADungeonEye::BeginPlay()
{
    APlayerController *controller = Cast<APlayerController>(GetController());
    
    if (nullptr == controller)
    {
        UE_LOG(LogTemp, Warning, TEXT("Dungeon eye failed to get controller."));
    }
    else
    {
        controller->SetPawn(this);
        controller->SetInitialLocationAndRotation(FVector(0.0, 175.0, 175.0), FRotator(0.0, 90.0, 0.0));
        SetActorLocation(FVector(0.0, 175.0, 175.0));
        SetActorRotation(FRotator(0.0, 90.0, 0.0));
    }
}

If I delete my “DungeonEye” from the scene and play it in the editor, then a DefaultPawn gets automatically generated and behaves perfectly…just without the headlight.

I also cannot select my custom pawn as the default pawn for the game in the project settings.

I am so frustrated and would be really grateful for anyone who can help me with this. I have been working on this for several days, originally just using a CameraActor with attached light and then a standard Actor with attached camera and light, and both behaved much the same.

I re-added my DungeonEye instance an now I can position it. Really not sure what happened there.

Maybe it is because yesterday the class inherited from CameraActor and I changed it to inherit from DefaultPawn since then.

Ijust realised I forgot to put a call to Super::BeginPlay(); in my BeginPlay() override implementation. I can now move the pawn around, Yay! However the light does not rotate with the pawn.

Any ideas? Should I somehow rotate it automatically based on the Controller’s current rotation, or the pawn’s current rotation? Advice would really be appreciated.

I’ve replaced my call in the constructor:

    m_light->SetupAttachment(RootComponent);

to this code in BeginPlay():

    if (!m_light->AttachToComponent(RootComponent,
                                    FAttachmentTransformRules(EAttachmentRule::SnapToTarget,
                                                              EAttachmentRule::SnapToTarget,
                                                              EAttachmentRule::KeepWorld,
                                                              false)))
    {
        UE_LOG(LogTemp, Warning, TEXT("Dungeon eye failed to attach light."));
    }

The warning doesn’t appear, yet I still get the problem.

This works. It is horrible and suggests that something else is seriously wrong somewhere:

void ADungeonEye::Tick(float delta_time)
{
    FRotator  rotation;

    Super::Tick(delta_time);

    // If we pump the control rotation from the controller into the light's relative rotation, then the
    // pitch input works at 90 degrees to the "forward" axis.
    rotation = GetController()->GetControlRotation();
    rotation.Yaw += 90.0;
    m_light->SetRelativeRotation(rotation);
}

Note: The eye’s starting position is rotated by 90 degrees to ensure it is looking at other things in the scene when it starts. Removing that rotation means that this works as expected without the 90 degree offset in this calculation.

FFS!!!