If I have an abstract parent class with BlueprintNativeEvent, the child class can override my function fine and will call the function when called by its base class in the world. However, I remove this function - I do not need it. Instead, I create a grandchild that overrides the function. In a vacuum, this normally works (although sometimes it does not, but I can’t reproduce it reliably).
However, if I return to the child class and override the function, the grandchild’s override becomes a new function entirely.
Reproducing the problem:
I have an abstract class in C++. We’ll call it Parent.
UCLASS(abstract, Blueprintable)
class PROJECT_API AParent : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AParent();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
bool TestFunc();
//Etc...
In my cpp file TestFunc looks like this:
bool AParent::TestFunc_Implementation()
{
unimplemented()
return false;
}
This compiles fine. I will now go into Unreal Engine 4’s editor and Create Blueprint class based on Parent. We’ll name this blueprint class Child.
And now this is where the problem arises. I will Create Blueprint class based on Child. I call it Grandchild… All it does is override Test Func and print out “Grandchild”. I now go and override Test Func in Child.
I drop Grandchild into the world. I go into Level Blueprint, and on BeginPlay() tell it to…
- Get all by class: Parent → For Each Loop
- For Each Loop → Loop Body
- Loop Body → Test Func
And now the problem: It prints “Child,” not “Grandchild”…
What seems to happen is that if Grandchild has Test Func defined and we then also override in parent, Grandchild’s Test Func becomes Test Func 0, which is not the same function.
Note:
This problem does not occur that I can tell if the original function is of type void, ie…
//.h file
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void TestFunc();
And…
//.cpp
void AParent::TestFunc_Implementation()
{
unimplemented()
}