How to do it...

  1. Create a new UInterface called Talker  (Creating the UTalker/ITalker classes):

  1. Add the following UFUNCTION implementation:
#pragma once

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

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UTalker : public UInterface
{
GENERATED_BODY()
};

/**
*
*/
class CHAPTER_08_API ITalker
{
GENERATED_BODY()

// Add interface functions to this class. This is the
// class that will be inherited to implement
// this interface.
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Talk)
void StartTalking();

};
  1. Create a new C++ class based on StaticMeshActor. Remember to check Show All Classes and find the class that way:

.

  1. After clicking Next, name this new class TalkingMesh:

  1. Add #include and modify the class declaration to include the talker interface:
#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "Talker.h"
#include "TalkingMesh.generated.h"

/**
*
*/
UCLASS()
class CHAPTER_08_API ATalkingMesh : public AStaticMeshActor, public ITalker
  1. Also, add the following functions to the class declaration:
UCLASS()
class CHAPTER_08_API ATalkingMesh : public AStaticMeshActor, public ITalker
{
GENERATED_BODY()

public:
ATalkingMesh();
void StartTalking_Implementation();
};
  1. Within the implementation, add the following to TalkingMesh.cpp:
#include "TalkingMesh.h"
#include "ConstructorHelpers.h"

ATalkingMesh::ATalkingMesh() : Super()
{
auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));

UStaticMeshComponent * SM = GetStaticMeshComponent();

if(SM != nullptr)
{
if (MeshAsset.Object != nullptr)
{
SM->SetStaticMesh(MeshAsset.Object);
SM->SetGenerateOverlapEvents(true);
}

SM->SetMobility(EComponentMobility::Movable);

}

SetActorEnableCollision(true);
}

void ATalkingMesh::StartTalking_Implementation()
{
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red,
TEXT("Hello there. What is your name?"));
}
  1. Create a new class based on DefaultPawn to function as our player character:

  1. Once you select Next, give the class a Name of TalkingPawn and select Create Class:

  1. Add the following to our class header:
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/DefaultPawn.h"
#include "Components/BoxComponent.h" // UBoxComponent
#include "TalkingPawn.generated.h"

/**
*
*/
UCLASS()
class CHAPTER_08_API ATalkingPawn : public ADefaultPawn
{
GENERATED_BODY()

public:
// Sets default values for this character's properties
ATalkingPawn();

UPROPERTY()
UBoxComponent* TalkCollider;

UFUNCTION()
void OnTalkOverlap(UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep,
const FHitResult & SweepResult);


};
  1. From the TalkingPawn.cpp file, make sure to include the following so that we have access to the ITalker and UTalker classes:
#include "TalkingPawn.h"
#include "Talker.h"
  1. Afterwards implement the constructor:
ATalkingPawn::ATalkingPawn() : Super()
{
// Set this character to call Tick() every frame. You can
// turn this off to improve performance if you
// don't need it.
PrimaryActorTick.bCanEverTick = true;

TalkCollider = CreateDefaultSubobject<UBoxComponent>("TalkCollider");

TalkCollider->SetBoxExtent(FVector(200, 200, 100));

TalkCollider->OnComponentBeginOverlap.AddDynamic(this, &ATalkingPawn::OnTalkOverlap);

TalkCollider->AttachTo(RootComponent);
}
  1. Implement OnTalkOverlap:
// Called to bind functionality to input
void ATalkingPawn::OnTalkOverlap(UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep,
const FHitResult & SweepResult)
{
auto Class = OtherActor->GetClass();
if (Class->ImplementsInterface(UTalker::StaticClass()))
{
ITalker::Execute_StartTalking(OtherActor);
}
}
  1. Compile your scripts. Create a new GameMode and set TalkingPawn as the default pawn class for the player. The quickest way to do this is to go to Settings | World Settings and then, under GameMode Overrideclick on the + button. From there, expand the Selected GameMode option and under Default Pawn Classselect TalkingPawn. Refer to the following screenshot:

  1.  Drag an instance of your ATalkingMesh class into the level. If you play the game now, you should be able to walk close to the mesh and see it display a message:

  1. Create a new Blueprint class based on ATalkingMesh by right-clicking on it from the Content Browser and selecting the appropriate option from the context menu:

 

  1. Name it MyTalkingMesh and select Create Blueprint Class:

  1. Inside the Blueprint Editor, create an implementation for StartTalking. We can do this by going to the Event Graph and right-clicking within the graph. Then, in the search bar, we can type in start talking. Under Add Eventselect the Event Start Talking option.

  1. If you would like to call the parent version of the event, you can right-click on the event node and select the Add call to parent function option:

  1. Afterward, you can connect the events together. To do something different from the original, create a Print String node and display a new In String message, such as I'm the overridden implementation in Blueprint. The final version of the example will look as follows:

  1. Compile your Blueprint. Afterwards, drag a copy of your new Blueprint into the level beside your ATalkingMesh instance.
  2. Walk up to the two actors and verify that your custom Pawn is correctly invoking either the default C++ implementation or the Blueprint implementation, as appropriate: