c++unreal-engine4unreal-engine5unreal-development-kit

Pointer to Incomplete class not allowed error


I'm trying to access the AddCoin() function from MainCharacter but it keeps prompting me with Pointer to incomplete class not allowed.

I've tried #including the MainCharacter.h but it keeps prompting Cannot open source file.

Casting the AActor to MainCharacter keeps resulting in a failed build.

It only allows including MainCharacter.generated.h

errors I get while building:

error C2027: use of undefined type 'AMainCharacter'
 E:\tutorial\Soul\Intermediate\Build\Win64\UE4Editor\Inc\Soul\MainCharacter.generated.h(99): note: see declaration of 'AMainCharacter'

MyCoinActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyCoinActor.generated.h"

UCLASS()
class SOUL_API AMyCoinActor : public AActor
{
    GENERATED_BODY()
    
public: 
    // Sets default values for this actor's properties
    AMyCoinActor();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UPROPERTY(VisibleAnywhere) UStaticMeshComponent* MyMesh;

    UPROPERTY(VisibleAnywhere) class USphereComponent *OverlapSphere;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    UFUNCTION() void OnBeginOverlapEvent(UPrimitiveComponent* OverlappedActor, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& sweepResult);
};

MyCoinActor.cpp

#include "MyCoinActor.h"
#include <Components/SphereComponent.h>

#include <MainCharacter.generated.h>

// Sets default values
AMyCoinActor::AMyCoinActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    OverlapSphere = CreateDefaultSubobject<USphereComponent>("Overlap_Sphere");
    OverlapSphere->InitSphereRadius(100.0f);
    OverlapSphere->SetCollisionProfileName("Trigger");
    RootComponent = OverlapSphere;

    MyMesh = CreateDefaultSubobject <UStaticMeshComponent>(TEXT("My Mesh"));
    MyMesh->SetupAttachment(RootComponent);


    OverlapSphere->OnComponentBeginOverlap.AddDynamic(this, &AMyCoinActor::OnBeginOverlapEvent);
}

// Called when the game starts or when spawned
void AMyCoinActor::BeginPlay()
{
    Super::BeginPlay(); 
}

// Called every frame
void AMyCoinActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

void AMyCoinActor::OnBeginOverlapEvent(UPrimitiveComponent* OverlappedActor, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& sweepResult) {
    AMainCharacter* MainCharacter = Cast<AMainCharacter>(OtherActor);
    if (MainCharacter != nullptr)
    {
        MainCharacter->AddCoin();
        Destroy();
    }
}

MainCharacter.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainCharacter.generated.h"

UCLASS()
class SOUL_API AMainCharacter : public ACharacter
{
    GENERATED_BODY()
        /** Camera boom positioning the camera behind the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category =
        Camera, meta = (AllowPrivateAccess = "true"))
        class USpringArmComponent* CameraBoom;
    /** Follow camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category =
        Camera, meta = (AllowPrivateAccess = "true"))
        class UCameraComponent* FollowCamera;


public:
    // Sets default values for this character's properties
    AMainCharacter();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    void MoveLeftRight(float Value);
    void MoveForwardBackward(float Value);
    UFUNCTION()
    void AddCoin();

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

MainCharacter.cpp

#include "MainCharacter.h"
#include "Components/InputComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Controller.h"


// Sets default values
AMainCharacter::AMainCharacter()
{
    // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    CameraBoom->SetupAttachment(RootComponent);
    CameraBoom->TargetArmLength = 300.0f; 
    CameraBoom->bUsePawnControlRotation = true;

    FollowCamera = CreateDefaultSubobject<UCameraComponent(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);

    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;

    GetCharacterMovement()->bOrientRotationToMovement = true;
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
}

// Called when the game starts or when spawned
void AMainCharacter::BeginPlay()
{
    Super::BeginPlay(); 
}

// Called every frame
void AMainCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

// Called to bind functionality to input
void AMainCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);
    PlayerInputComponent->BindAxis("MoveForwardBackward", this, &AMainCharacter::MoveForwardBackward);
    PlayerInputComponent->BindAxis("MoveLeftRight", this, &AMainCharacter::MoveLeftRight);
    PlayerInputComponent->BindAxis("LookLeftRight", this,
        &APawn::AddControllerYawInput);
    PlayerInputComponent->BindAxis("LookUpDown", this,
        &APawn::AddControllerPitchInput);

    PlayerInputComponent->BindAction("Jump",IE_Pressed, this, &AMainCharacter::Jump);
    PlayerInputComponent->BindAction("Jump",IE_Released, this, &AMainCharacter::StopJumping);
}


void AMainCharacter::MoveForwardBackward(float Value)
{
    if ((Controller != NULL) && (Value != 0.0f))
    {
        // find out which way is forward
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);
        // get forward vector
        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
        AddMovementInput(Direction, Value);
    }
}
void AMainCharacter::MoveLeftRight(float Value)
{
    if ((Controller != NULL) && (Value != 0.0f))
    {
        // find out which way is right
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);
        // get right vector
        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
        // add movement in that direction
        AddMovementInput(Direction, Value);
    }
}


void AMainCharacter::AddCoin() {

}
``

Solution

  • I was tring to include both MainCharacter.generated.h and Maincharacter.h and that was causing some error. I commented out MainCharacter.generated.h and including MainCharacter.h and it seems to be working fine.