How to properly use Blueprint Native Event?

Here’s my situation. I’m trying to have a base parent class (UsableActor) and a child class that extends from it (UsableActorActivator)

I need UsableActor to have a function called OnUsed, and I need UsableActorActivator to override this function.

However, I want to be able to create a child blueprint of UsableActorActivator and a create an event of OnUsed, to add more functionality content wise. I’m aware that BlueprintNativeEvent is where I should be looking at, but not sure exactly how to use it.

How would this sort of function be set up? I’m always getting some sort of compilation error when trying to do it, so it’d be nice to see a correct implementation of it if possible.

Thanks,
Lucas

Hey Higuy8000,

I am not sure about “properly” but this is how I would go about doing what you’ve described:

[UsableActor.h]

#pragma once

#include "GameFramework/Actor.h"
#include "UsableActor.generated.h"

UCLASS()
class AH501041_API AUsableActor : public AActor
{
	GENERATED_BODY()
	
public:	
	AUsableActor();
	virtual void BeginPlay() override;
	virtual void Tick( float DeltaSeconds ) override;

    UFUNCTION( BlueprintNativeEvent, BlueprintCallable, Category = "UsableActor" )
    void OnUsed( );

protected:

    virtual void OnUsedInternal( );
};

[UsableActor.cpp]

#include "AH501041.h"
#include "UsableActor.h"

AUsableActor::AUsableActor()
{
	PrimaryActorTick.bCanEverTick = true;

}

void AUsableActor::BeginPlay()
{
	Super::BeginPlay();
	
    // This is the "event" OnUsed is being called at
    // Normally, this would be done at the actual interaction event
    // up to you to change how this works.
    OnUsed( );
}

void AUsableActor::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

}

void AUsableActor::OnUsed_Implementation( )
{
    OnUsedInternal( );   
}

// Because BlueprintNativeEvent can't be virtual, have the native event call a virtual function.
// This allows child class to override virtual for different / additional functionality.
void AUsableActor::OnUsedInternal( )
{    
    UE_LOG( LogTemp, Warning, TEXT("AUsableActor: %s"), *GetName( ) );
}

[UsableActorActivator.h]

#pragma once

#include "UsableActor.h"
#include "UsableActorActivator.generated.h"

UCLASS()
class AH501041_API AUsableActorActivator : public AUsableActor
{
	GENERATED_BODY()
public:
    virtual void BeginPlay( ) override;
    
    UFUNCTION( BlueprintNativeEvent, BlueprintCallable, Category = "UsableActor" )
    void OnUsed( );
    
protected:
    virtual void OnUsedInternal( ) override;
};

[UsableActorActivator.cpp]

#include "AH501041.h"
#include "UsableActorActivator.h"

void AUsableActorActivator::BeginPlay( )
{
	Super::BeginPlay();
}

void AUsableActorActivator::OnUsed_Implementation( )
{
    OnUsedInternal( );
}

void AUsableActorActivator::OnUsedInternal( )
{
    Super::OnUsedInternal( );
    
    UE_LOG( LogTemp, Warning, TEXT("AUsableActorActivator: %s"), *GetName( ) );
}

[Output]

UsableActor:

LogTemp:Warning: AUsableActor: UsableActor_BP_451

UsableActorActivator:

LogTemp:Warning: AUsableActor: UsableActorActivator_BP_170
LogTemp:Warning: AUsableActorActivator: UsableActorActivator_BP_170

As you can see the UsableActorActivator inherits whatever functionality that UsableActor has inside of “OnUsedInternal”. This should give you the freedom to either override completely or take on functionality in the child class.

Sweet! Thank you so much for all of this, it helped and explained quite a lot :slight_smile:

Actually you don’t need OnUsedInternal( ) because OnUsed_Implementation( ) is virtual by itself, so you can override it.

6 Likes