Quick answer: The target actor does not actually implement the interface. Open its Class Settings, add the interface to Implemented Interfaces, and override the function. Use the Message variant of the call (not the Event variant) so the dispatch is dynamic and you do not need a cast.

Blueprint Interfaces are the cleanest way to decouple actors in Unreal — until you write a function that should return the player’s health and it always returns zero. The actor exists, the interface looks fine, the wires are connected, and yet the value is wrong. The problem is almost always one of three things, and you can rule out all three in two minutes.

The Symptom

You define an interface with a function like GetHealth() -> float. You call it on an actor reference and get back 0.0, even though you are looking at the actor in the world and you can see its health bar. The behavior:

What Causes This

Cause 1: The actor does not actually implement the interface.

Adding a function to a Blueprint Interface and pointing your call at an actor reference does not magically make that actor support the interface. The actor must explicitly add the interface to its Class Settings → Implemented Interfaces list and override the function. Without this, the call falls through to the empty default implementation, which returns whatever the function’s default return value is — usually zero.

Cause 2: The actor was inherited from a C++ class that implements the interface in code, but the Blueprint child does not override the function.

C++ interfaces are tricky here. If the parent C++ class declares the interface but only has stub implementations, the Blueprint child needs to add the interface again in Class Settings to expose the override slot.

Cause 3: You are calling the Event variant instead of the Message variant.

Unreal exposes two ways to call an interface function. The Event variant requires the target to be cast to the interface type and dispatches statically. The Message variant takes a generic Actor reference and dispatches dynamically. The Message variant is the one that does the right thing for polymorphism — if you are using Event and your variable is typed as Actor, the call falls through to the default.

The Fix

Step 1: Verify the actor implements the interface.

Open the actor Blueprint. Click Class Settings in the toolbar. Look at the Implemented Interfaces section in the Details panel. Your interface should be in the list. If it is not, click Add, search for it, and add it. Save and recompile.

Now go to the My Blueprint panel under Interfaces. You should see the interface functions listed. Right-click each function you want to support and pick Implement Event. Wire up the return value to the actual data the actor holds.

Step 2: Use the Message variant.

In the calling Blueprint, drag off the Actor reference and search for your interface function. You will see two entries:

Always pick the Message version unless you have a strong reason to demand the interface type at compile time. The Message version is the one that respects runtime polymorphism.

Step 3: Guard with Does Implement Interface.

Even with the Message variant, calling the interface on an actor that does not implement it silently returns defaults. To make the failure explicit, branch on Does Implement Interface before the call:

// Pseudocode for the Blueprint graph
Branch:
    Condition: DoesImplementInterface(Target, BPI_Damageable)
    True:
        var health = GetHealth_Message(Target)
        // use health
    False:
        PrintString("Target does not implement BPI_Damageable")

This converts a silent zero into a loud error message, which is what you want during development.

C++ Implementation Gotchas

If your interface mixes C++ and Blueprint, the function must be declared with BlueprintNativeEvent (or BlueprintImplementableEvent) for Blueprint children to override it. A pure virtual C++ function or a non-Blueprint UFUNCTION cannot be overridden in a Blueprint.

// IDamageable.h - correct declarations for mixed use
UINTERFACE(BlueprintType)
class UDamageable : public UInterface { GENERATED_BODY() };

class IDamageable
{
    GENERATED_BODY()
public:
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Damage")
    float GetHealth() const;
    virtual float GetHealth_Implementation() const { return 0.0f; }
};

Verifying the Fix

Add a Print String to the actor’s implementation of the interface function and another inside the calling Blueprint. Trigger the call. Both prints should fire in order. If only the calling print fires, the actor does not actually implement the interface — go back to Class Settings.

“Blueprint Interfaces feel like duck typing, but they are not. The actor has to opt in. If you forget to opt in, the call silently returns nothing — and that silent nothing has shipped a hundred broken games.”

Related Issues

For Blueprint cast failures that look similar, see Unreal Blueprint cast always failing. For events that should fire but never do, check Unreal Blueprint event not firing. If your interface call works but the data is wrong, see Unreal Data Asset changes not saving.

If a Blueprint Interface call returns zero, the first thing to check is the target’s Class Settings. If the interface is not in the list, the actor does not implement it — period.