Cannot dynamic cast with RTTI enabled

Hello,

I have created a module that contains a custom GameplayDebuggerCategory. Inside the CollectData function I’ve got the following code:

void FGameplayDebuggerCategory_Orfeas::CollectData(APlayerController* OwnerPC, AActor* DebugActor)
{
	if (DebugActor)
	{
		//works fine
		//AGDBlogPostCharacter* Char = static_cast<AGDBlogPostCharacter*>(DebugActor);

		//throws a linker error
		AGDBlogPostCharacter* Char = dynamic_cast<AGDBlogPostCharacter*>(DebugActor);


		if (Char)
		{
			GLog->Log("HP: " + FString::SanitizeFloat(Char->Health));
			GLog->Log("Dmg: " + FString::SanitizeFloat(Char->MaxDamage));

			Data.HP = Char->Health;
			Data.Damage = Char->MaxDamage;

		}
	}
}

I tried using the Cast that comes with UObjects as well with the same result (I think this is expected though since cast acts as a dynamic cast sometimes?).
In order to use the dynamic cast I guess that I need to activate the Run-time Type Information. I’ve searched the forums a bit and came up with this post that mentions that I need to mark the bUseRTTI as true inside my ProjectName.Build.cs file. Of course, I gave this a try but it doesn’t seem to work. Moreover, I attempted to mark that property as true inside my module’s build.cs file but the linker error still appears.

Besides the above post, I came up with this post as well that mentions that you cannot enable RTTI in modules that contain UObjects. My code doesn’t contain any UObjects (if by “contain” it means that we have declared something there).

In order to create the GameplayDebuggerCategory I’m using the code from the AIModule as an example. However, as seen here the Cast<> function is used just fine, so what am I missing? I took a look at the AIModule.build.cs file and it doesn’t declare that RTTI is enabled.

Just to clarify, I can get away using the static cast in my code snippet above but since the Character is a polymorphic type I would like to use dynamic cast instead since that would be optimal.

Thanks in advance,

Orfeas

What is the AGDBlogPostCharacter? If you’re sticking to UE4’s naming convention then that’s an actor, and an actor is an UObject, so yeah, you’re using UObjects (and “using” is enough in this context). In general UE4 code Cast<> should just work without any need to enable any additional flags. BTW, using dynamic_cast on UObject classes boils down do using Cast<>.

My gut tell me your gameplay debugger category is in a module that doesn’t link to whatever module defines AGDBlogPostCharacter. But I’d need to see the linker error message to be able to tell for sure.

Cheers,

–mieszko

The linker error you get can result from two things: GDBlogPost project not declaring all its dependencies properly (which doesn’t seem to be the case) or AGDBlogPostCharacter (which I assume lives in the OrfeasModule) not being exported as module’s API. Try adding the export tag to AGDBlogPostCharacter, like so:

class ORFEASMODULE_API AGDBlogPostCharacter ...

(again, assuming it’s in OrfeasModule, if not adjust the *_API tag)

Hope it helps.

–mieszko

Hey Mieszko, thanks for your quick reply!

I’m sticking to UE4’s naming convention. So, here is a screenshot of the linker error:

I’m working on a project named GDBlogPost so inside the constructor in the .build.cs file I have the following dependencies:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "OrfeasModule" });

Moreover, here is the constructor of the “OrfeasModule” which contains the GameplayDebuggerCategory class:

PublicIncludePaths.AddRange(new string[] { "OrfeasModule/Public" });

        PrivateIncludePaths.AddRange(new string[] { "OrfeasModule/Private" });

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "GDBlogPost" });
        
        if (UEBuildConfiguration.bBuildDeveloperTools || (Target.Configuration != UnrealTargetConfiguration.Shipping && Target.Configuration != UnrealTargetConfiguration.Test))
        {
            PrivateDependencyModuleNames.Add("GameplayDebugger");
            Definitions.Add("WITH_GAMEPLAY_DEBUGGER=1");

            bUseRTTI = true;
        }
        else
        {
            Definitions.Add("WITH_GAMEPLAY_DEBUGGER=0");
            bUseRTTI = false;
        }

I made sure to include the header file of the AGDBlogPostCharacter on my category’s source file as well.

Am I missing something obvious?

Thanks for your help,

Orfeas

That did the trick - thank you so much Mieszko!

-Orfeas