Interfaces And Blueprints

Using interfaces with C++ and Blueprints can be a little tricky when the interface is implemented purely in Blueprints. Currently, when a Blueprint implements an Interface the C++ InterfaceCast\ ty...

Updated almost 3 years ago Edit Page Revisions

Using interfaces with C++ and Blueprints can be a little tricky when the interface is implemented purely in Blueprints. Currently, when a Blueprint implements an Interface the C++ InterfaceCast\ type cast does not work.

Interface Cast Method

auto MyInterface = InterfaceCast(ActorInstance);
if (MyInterface)
{
  // Other code
}

What you need to do instead is:

(Originally discovered by Lion032, source)

Implements Interface Method

if (ActorInstance->GetClass()->ImplementsInterface(UMyInterface::StaticClass()))
{
  // Other code
}

This will work for both C++ implemented interfaces and Blueprint implemented interfaces. From here, you can use the static Execute versions of the interface functions.

Header:

UINTERFACE(MinimalAPI)
class UMyInterface : public UInterface
{
  GENERATED_UINTERFACE_BODY()
};
 
class IMyInterface
{
  GENERATED_IINTERFACE_BODY()

public:
  UFUNCTION(BlueprintImplementableEvent)
  void MyInterfaceFunction();
};

Interface function example:

if (ActorInstance->GetClass()->ImplementsInterface(UMyInterface::StaticClass()))
{
  IMyInterface::Execute_MyInterfaceFunction(ActorInstance);
}

It is likely that the static Execute functions are generated by the Unreal Header Tool (UHT) only for interface functions that declare UFUNCTION(). This means that you can't make a virtual interface function which uses UFUNCTION() and intellisense won't pick them up.

More Complete Example (Passing Self as Reference):

MyInterface.H:


class AMyActor;

UINTERFACE(Category = "My Interface", BlueprintType, meta = (DisplayName = "My Interface"))
class MYMODULE_API UMyInterface : public UInterface {
    GENERATED_UINTERFACE_BODY()
};

class MYMODULE_API IMyInterface {
    GENERATED_IINTERFACE_BODY()
public:
    /// My Initialization Interface.
    UFUNCTION(Category = "My Interface", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "On My Interface Execute")
    void OnInitialized(const AMyActor* Context);
};

MyActor.H:

UFUNCTION(Category = "My Interface", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "On My Interface Call"))
void OnInitialized(const AMyActor* Context);

MyActor.CPP:


void AMyActor::OnInitialized_Implementation(const AMyActor* Context) {

    if (Context != this) {return;}

    TArrayInterfaces;
    // Pick only Actors with Interface, instead of iterating whole World:
    UGameplayStatics::GetAllActorsWithInterface(this,UMyInterface::StaticClass(),Interfaces);

    for (const auto &Actor : Interfaces) {

        // Try to Execute on C++ layer:
        const auto &Interface = Cast(Actor);
        if (Interface) {Interface->Execute_OnInitialized(Actor,Context);} else
        
        // Else, Execute Interface on Blueprint layer instead:
        if (Actor->GetClass()->ImplementsInterface(UMyInterface::StaticClass())) {
            IMyInterface::Execute_OnInitialized(Actor,Context);
        }

    }

}

void AMyActor::BeginPlay() {
    Super::BeginPlay();

    // Fire off the Native Event, which is going to be received by all the other Actors:
    Execute_OnInitialized(this,this);

}

Notes: Example above is implemented with old GENERATED_UCLASS_BODY() instead of new GENERATED_BODY() one. If you want your Actor to receive C++ Interface calls instead of from Blueprint layer, your Actor must inherit from both AActor class and your Interface class, like so:

class MYMODULE_API AMyActor : public AActor, public IMyInterface {...}

Update and pointer to more detailed discussion

Thanks for this wiki; I think it is essential on getting interfaces to work properly. I wrote a longer discussion of what I think is going on with Blueprint and C++ interfaces at which I thought readers of this topic might find useful. -Xarol

,