Chapter 19

C++ Interfaces (UINTERFACE)

The U/I class split behind every C++ interface, which function specifier lets Blueprint override what, and how a call actually dispatches.

In this chapter

  1. The Two Classes
  2. Which Specifier Gives Blueprint What
  3. Calling Through an Interface
  4. Gotchas
1

The Two Classes

A C++ interface is always two types: a UINTERFACE (reflection-facing) and the actual I-prefixed class you implement against.

// HealthChangeListener.h
UINTERFACE(MinimalAPI, Blueprintable)
class UHealthChangeListener : public UInterface
{
    GENERATED_BODY()
};

class IHealthChangeListener
{
    GENERATED_BODY()
public:
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Health")
    void OnHealthChanged(float NewHealth);
};

2

Which Specifier Gives Blueprint What

SpecifierGives you
BlueprintNativeEventA C++ default implementation and lets Blueprint override it. Usually what you want for a cross-language interface. Implement the default in C++ as OnHealthChanged_Implementation
BlueprintImplementableEventZero C++ default behavior — no _Implementation override possible or needed. Use when only Blueprint will ever provide the body
Plain UFUNCTION()C++-only. Blueprint can't override or implement it, even if the UINTERFACE itself is Blueprintable
The interface-level specifier and the per-function specifier are separate. Marking the UINTERFACE Blueprintable only opens the door for a Blueprint class to implement the interface at all — it doesn't make any individual function overridable. That still comes down to BlueprintNativeEvent / BlueprintImplementableEvent on the function itself.

3

Calling Through an Interface

A call dispatches to whichever implementation is "closest" — a Blueprint override if present, otherwise the C++ _Implementation:

if (TargetActor->Implements<UHealthChangeListener>())
{
    IHealthChangeListener::Execute_OnHealthChanged(TargetActor, 75.0f);
}

Implements<T>() checks whether an actor's class implements the interface at all, without knowing its concrete type — the same decoupling win Blueprint Interfaces give you (Chapter 2), just from C++. Execute_OnHealthChanged is UHT-generated per BlueprintNativeEvent/BlueprintImplementableEvent function and is always the correct way to call one, rather than calling _Implementation directly or casting to the interface and calling the function bare.


4

Gotchas

Interview drill

Answer each out loud before re-reading the chapter.

  1. Why does a C++ interface need two classes, and what does each one do?
  2. What's the difference between BlueprintNativeEvent and BlueprintImplementableEvent, and when do you reach for each?
  3. How do you check whether an actor implements an interface, and how do you call through it correctly?
← Chapter 18 ↑ Index Chapter 20 →