Static function call generated by UHT.

I’m looking at someone else’s code and I find this. It’s a static function call from an interface, oddly enough, a function generated by the Unreal Build Tool. Is this common practice? Aren’t there less obscure ways to do these things?

The context, a function on the PlayerController bound to pressing the E key. That function is Action.

I have seen that the method declared in the interface is a BlueprintNativeEvent, is it calling that method generated by the UHT to directly call the blueprint “event”, and that said event calls the correct method?

void AHowToCharacter::Action()
{

	if (CurrentInteractive != nullptr)
	{
		// Execute the interact event
		IInteractable::Execute_OnInteract(CurrentInteractiveActor); 
	}
}
#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interactable.generated.h"

UINTERFACE(MinimalAPI)
class UInteractable : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class HOWTO_API IInteractable
{
	GENERATED_BODY()

public:

	virtual FName GetName() = 0;

	virtual FName GetQuestID() = 0;

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interact")
	void OnInteract();
	
};

“Is this a common practice?” Yes and no. This is one of those cases where Unreal C++ diverges from “regular” C++.

The first thing to know is that interfaces implemented by blueprint classes don’t have an actual memory address. So in your case if you have an AActor* and the blueprint implements IInteractable there’s no way to actually get an IInteractable*. And if you try to cast an object to the interface, you may get nullptr even though it actually implements the interface.

This means that it’s not actually possible to make a call like this->OnInteract.

The auto generated Execute_ is then a wrapper to properly call the proper function regardless of whether the implementation is in blueprint or C++.

There is a UINTERFACE meta tag, CannotImplementInterfaceInBlueprint, which disallows the possibility of a blueprint implementation. This guarantees that all implementations are in C++ and you can rely on interface pointers and casts. The Execute_ function still exist (I think) but you no longer have to use them.

1 Like