Using _Implementation and BlueprintNativeEvent

Hello to all,

I use UE 4.7 and I have two files a .cpp and a .h:

in the .h:


/** called when something enters the sphere component */
UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
virtual void OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

/** called when something leaves the sphere component */
UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
virtual void OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);


in the .cpp:


void ALightSwitchBoth::OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

And when I compile the project, I will get the errors:

1>------ Build started: Project: CPPCode, Configuration: Development_Editor x64 ------
1> Compiling game modules for hot reload
1> Parsing headers for CPPCodeEditor
1>D:/Unreal Projects/CPPCode/Source/CPPCode/LightSwitchBoth.h(28): error : In LightSwitchBoth: BlueprintNativeEvent functions must be non-virtual.
1>Error : Failed to generate code for CPPCodeEditor - error code: OtherCompilationError (2)
1> UnrealHeaderTool failed for target ‘CPPCodeEditor’ (platform: Win64, module info: D:\Unreal Projects\CPPCode\Intermediate\Build\Win64\CPPCodeEditor\Development\UnrealHeaderTool.manifest).
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.MakeFile.Targets(38,5): error MSB3073: The command ““D:\Program Files\Epic Games\4.7\Engine\Build\BatchFiles\Build.bat” CPPCodeEditor Win64 Development “D:\Unreal Projects\CPPCode\CPPCode.uproject” -rocket” exited with code -1.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

So can I use virtual functions or not with _implementation? What do I do wrong?

You’re doing it wrong. The header should read


UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
void OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

virtual void OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

The implementation is the virtual function that contains all the behaviour and which can be overridden by the blueprint. It actually has to be virtual. Since I don’t know how the header tool works, I always think of the BlueprintNativeEvent function declaration as a sort of label for the implementation function. As such, it makes no sense to be virtual since you never add any implementation under the label anyways, so overriding it in a derived class would be pointless.

2 Likes

Thank you for your patience and posts.
Sorry, the code you wrote above, should be in the header (.h)? What am I doing wrong? I tried many ways - all the time errors.

You need to split the declaration into two parts, the Event and the Implementation function. Example, a simple actor that prints a string

header


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

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

UCLASS()
class EMPTYTEST_API AStringActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AStringActor();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	UFUNCTION(BlueprintNativeEvent, Category = "StringActor")
	void PrintMe();

	virtual void PrintMe_Implementation();
	
};


source


// Fill out your copyright notice in the Description page of Project Settings.

#include "EmptyTest.h"
#include "StringActor.h"


// Sets default values
AStringActor::AStringActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AStringActor::BeginPlay()
{
	Super::BeginPlay();
	PrintMe();
}

// Called every frame
void AStringActor::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

}

void AStringActor::PrintMe_Implementation()
{
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Weee"));
	}
}

You can override the PrintMe function by creating a blueprint class from StringActor and implementing the event in its event graph. I just implemented this and it works on my end.

My code:

header:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once

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

/**
*
*/
UCLASS()
class CPPCODE_API ALightSwitchBoth : public AActor
{
	GENERATED_BODY()
public:
	/** point light component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class UPointLightComponent* PointLight1;

	/** sphere component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class USphereComponent* Sphere1;

	ALightSwitchBoth(const FObjectInitializer& ObjectInitializer);

	/** called when something enters the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
		 virtual void OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	/** called when something leaves the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
		 virtual void OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	/** Toggles the light component's visibility*/
	UFUNCTION()
		void ToggleLight();

	/** the desired intensity for the light */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Switch Variables")
		float DesiredIntensity;

};

source:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "CPPCode.h"
#include "LightSwitchBoth.h"

ALightSwitchBoth::ALightSwitchBoth(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{

	DesiredIntensity = 3000.0f;

	PointLight1 = ObjectInitializer.CreateDefaultSubobject<UPointLightComponent>(this, "PointLight1");
	PointLight1->Intensity = DesiredIntensity;
	PointLight1->bVisible = true;
	RootComponent = PointLight1;

	Sphere1 = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("Sphere1"));
	Sphere1->InitSphereRadius(250.0f);
	Sphere1->AttachParent = RootComponent;

	Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapBegin);       // set up a notification for when this component overlaps something
	Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapEnd);       // set up a notification for when this component overlaps something
}

void ALightSwitchBoth::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::OnOverlapEnd(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::ToggleLight()
{
	PointLight1->ToggleVisibility();
}

EDIT:

I see I have no _Implementation in the source file.

Try changing it to

header:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once

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

/**
*
*/
UCLASS()
class CPPCODE_API ALightSwitchBoth : public AActor
{
	GENERATED_BODY()
public:
	/** point light component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class UPointLightComponent* PointLight1;

	/** sphere component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class USphereComponent* Sphere1;

	ALightSwitchBoth(const FObjectInitializer& ObjectInitializer);

	/** called when something enters the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
	void OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	virtual void OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	/** called when something leaves the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
	void OnOverlapEnd(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	virtual void OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	/** Toggles the light component's visibility*/
	UFUNCTION()
		void ToggleLight();

	/** the desired intensity for the light */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Switch Variables")
		float DesiredIntensity;

};

source:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "CPPCode.h"
#include "LightSwitchBoth.h"

ALightSwitchBoth::ALightSwitchBoth(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{

	DesiredIntensity = 3000.0f;

	PointLight1 = ObjectInitializer.CreateDefaultSubobject<UPointLightComponent>(this, "PointLight1");
	PointLight1->Intensity = DesiredIntensity;
	PointLight1->bVisible = true;
	RootComponent = PointLight1;

	Sphere1 = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("Sphere1"));
	Sphere1->InitSphereRadius(250.0f);
	Sphere1->AttachParent = RootComponent;

	Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapBegin);       // set up a notification for when this component overlaps something
	Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapEnd);       // set up a notification for when this component overlaps something
}

void ALightSwitchBoth::OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::ToggleLight()
{
	PointLight1->ToggleVisibility();
}

Now my code:

header:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once

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

/**
*
*/
UCLASS()
class CPPCODE_API ALightSwitchBoth : public AActor
{
	GENERATED_BODY()
public:
	/** point light component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class UPointLightComponent* PointLight1;

	/** sphere component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Switch Components")
	class USphereComponent* Sphere1;

	ALightSwitchBoth(const FObjectInitializer& ObjectInitializer);

	/** called when something enters the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
		 virtual void OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	/** called when something leaves the sphere component */
	UFUNCTION(BlueprintNativeEvent, Category = "Switch Functions")
		 virtual void OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	/** Toggles the light component's visibility*/
	UFUNCTION()
		void ToggleLight();

	/** the desired intensity for the light */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Switch Variables")
		float DesiredIntensity;

};

source:


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "CPPCode.h"
#include "LightSwitchBoth.h"

ALightSwitchBoth::ALightSwitchBoth(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{

	DesiredIntensity = 3000.0f;

	PointLight1 = ObjectInitializer.CreateDefaultSubobject<UPointLightComponent>(this, "PointLight1");
	PointLight1->Intensity = DesiredIntensity;
	PointLight1->bVisible = true;
	RootComponent = PointLight1;

	Sphere1 = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("Sphere1"));
	Sphere1->InitSphereRadius(250.0f);
	Sphere1->AttachParent = RootComponent;

	Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapBegin);       // set up a notification for when this component overlaps something
	Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlapEnd);       // set up a notification for when this component overlaps something
}

void ALightSwitchBoth::OnOverlapBegin_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::OnOverlapEnd_Implementation(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		ToggleLight();
	}
}

void ALightSwitchBoth::ToggleLight()
{
	PointLight1->ToggleVisibility();
}

And still I get errors.

1>------ Build started: Project: CPPCode, Configuration: Development_Editor x64 ------
1> Compiling game modules for hot reload
1> Parsing headers for CPPCodeEditor
1>D:/Unreal Projects/CPPCode/Source/CPPCode/LightSwitchBoth.h(28): error : In LightSwitchBoth: BlueprintNativeEvent functions must be non-virtual.
1>Error : Failed to generate code for CPPCodeEditor - error code: OtherCompilationError (2)
1> UnrealHeaderTool failed for target ‘CPPCodeEditor’ (platform: Win64, module info: D:\Unreal Projects\CPPCode\Intermediate\Build\Win64\CPPCodeEditor\Development\UnrealHeaderTool.manifest).
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.MakeFile.Targets(38,5): error MSB3073: The command ““D:\Program Files\Epic Games\4.7\Engine\Build\BatchFiles\Build.bat” CPPCodeEditor Win64 Development “D:\Unreal Projects\CPPCode\CPPCode.uproject” -rocket” exited with code -1.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The most important is:

BlueprintNativeEvent functions must be non-virtual.

It should be virtual in UE 4.7, so why such an error?

Thank you, alpaka, it works!

But I completely don’t understand why we are forced to write OnOverlapBegin and OnOverlapEnd two times.

It’s because in previous versions of the engine, the _Implementation (and _Validate for Server functions) were auto-generated for you by UBT when you built.

Epic removed that in 4.7, although I still prefer the old method personally.

1 Like