Hi all! I’m having some trouble getting custom modules working, for reference I’m using UE 5.2, jetbrains rider, vs 2019.
I’ve been trying to structure my code using modules but it seems to break whenever I try to import anything into my core game module with an unresolved external symbol error:
LNK2019: unresolved external symbol "private: static class UClass * __cdecl UInteractable::GetPrivateStaticClass(void)" (?GetPrivateStaticClass@UInteractable@@CAPEAVUClass@@XZ) referenced in function "private: void __cdecl AMainGamePlayerController::ClearLookAtTarget(void)" (?ClearLookAtTarget@AMainGamePlayerController@@AEAAXXZ)
My relevant directory structure is as follows:
Source/
MainGame/
Controllers/
Player/
MainGamePlayerController.h
MainGamePlayerController.cpp
InteractionModule/
Public/
Core/
InteractionModule.h
InteractionModule.cpp
Interfaces/
Interactable.h
Interactable.cpp
and the relevant files look like this:
MainGame.Build.cs
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class MainGame : ModuleRules
{
public MainGame(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PrivateDependencyModuleNames.AddRange(new string[] {"InteractionModule"});
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput" });
}
}
MainGame.uproject
{
"FileVersion": 3,
"EngineAssociation": "5.2",
"Category": "",
"Description": "",
"Modules": [
{
"Name": "MainGame",
"Type": "Runtime",
"LoadingPhase": "Default",
"AdditionalDependencies": [
"Engine"
]
},
{
"Name": "InteractionModule",
"Type": "Runtime"
}
],
"Plugins": [
{
"Name": "ModelingToolsEditorMode",
"Enabled": true,
"TargetAllowList": [
"Editor"
]
}
]
}
InteractionModule.Build.cs
using UnrealBuildTool;
public class InteractionModule : ModuleRules
{
public InteractionModule(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore"
}
);
}
}
InteractionModule.h
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FInteractionModule : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
Interactable.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interactable.generated.h"
// This class does not need to be modified.
UINTERFACE(BlueprintType)
class UInteractable : public UInterface
{
GENERATED_BODY()
};
/**
* Common interface for objects which can be interacted with
*/
class INTERACTIONMODULE_API IInteractable
{
GENERATED_BODY()
public:
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interaction")
bool CanInteract();
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interaction")
bool ShouldInteract();
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Highlight")
bool IsHighlightable();
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interaction")
void Interact();
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Highlight")
void Highlight();
/*
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Highlight")
void UnHighlight();
};
MainGamePlayerController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainGamePlayerController.h"
#include "InteractionModule/Public/Interfaces/Interactable.h"
#include "Kismet/KismetMathLibrary.h"
AMainGamePlayerController::AMainGamePlayerController()
{
LookAtQueryParams.AddIgnoredActor(GetPawn());
LookAtQueryParams.bTraceComplex = false;
}
void AMainGamePlayerController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
UpdateLookAtTarget();
}
#pragma region perception
void AMainGamePlayerController::UpdateLookAtTarget()
{
FHitResult HitResult;
BuildLookAtTrace(HitResult);
if (HitResult.IsValidBlockingHit())
{
const auto Target = HitResult.GetActor();
if (IsValid(Target))
{
SetLookAtTarget(*Target);
}
else
{
ClearLookAtTarget();
}
}
else
{
ClearLookAtTarget();
}
}
void AMainGamePlayerController::BuildLookAtTrace(FHitResult& OutHitResult) const
{
FVector OriginLocation;
FRotator OriginRotation;
GetPlayerViewPoint(OriginLocation, OriginRotation);
const FVector EndLocation = UKismetMathLibrary::GetForwardVector(OriginRotation) * MaxLookAtDistance + OriginLocation;
ActorLineTraceSingle(OutHitResult, OriginLocation, EndLocation, ECC_Visibility, LookAtQueryParams);
}
void AMainGamePlayerController::SetLookAtTarget(AActor& NewLookAtTarget)
{
if (&NewLookAtTarget != LastLookedAtTarget.Get())
{
ClearLookAtTarget();
TryLookAtInteractable(NewLookAtTarget);
LastLookedAtTarget = &NewLookAtTarget;
}
}
void AMainGamePlayerController::ClearLookAtTarget()
{
TryLookAwayFromInteractable();
LastLookedAtTarget = nullptr;
}
void AMainGamePlayerController::TryLookAtInteractable(AActor& LookAtTarget) const
{
const auto Interactable = Cast<IInteractable, AActor>(&LookAtTarget);
if (Interactable != nullptr && Interactable->IsHighlightable())
{
Interactable->Highlight();
}
}
void AMainGamePlayerController::TryLookAwayFromInteractable() const
{
const auto Interactable = Cast<IInteractable, AActor>(LastLookedAtTarget.Get());
if (Interactable != nullptr && Interactable->IsHighlightable())
{
Interactable->UnHighlight();
}
}
#pragma endregion perception
I’ve done the usual regeneration of project files a bazillion times it feels but no matter what I try this error remains… I can see the module being built with the solution, so it seems to be getting included correctly, so I suspect maybe my import is incorrect? Any help would be enormously appreciated as this has been giving me the run around for a few days now