Interface在C++中的语法及使用
判断是否实现接口(参考):
- Implements<T>();
- IxxxInterface* TheInterface = Cast<IxxxInterface>(obj);
若是C++里定义的接口,在蓝图里进行了实现,则在C++里通过该对象进行接口调用的方法如下:
auto Owner = GetOwner<APawn>(); if (Owner && Owner->GetClass()->ImplementsInterface(UAnjUpdatePoseInterface::StaticClass())) { IAnjUpdatePoseInterface::Execute_OnPoseUpdate(Owner, PoseData); }
UInterface and IInterface
///////// header file ///////// #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "UObject/Interface.h" #include "WhenCalled.generated.h" class IWhenCalledInterface; class UWhenCalledInterface; UINTERFACE(BlueprintType, MinimalAPI) class UWhenCalledManagerInterface: public UInterface { GENERATED_UINTERFACE_BODY() }; class SURAXR_API IWhenCalledManagerInterface { GENERATED_IINTERFACE_BODY() public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="SURAXR") int AddHandler(const TScriptInterface<IWhenCalledInterface>& Handler); virtual void BindDelegates() = 0; }; UINTERFACE(BlueprintType, MinimalAPI) class UWhenCalledInterface: public UInterface { GENERATED_UINTERFACE_BODY() }; class SURAXR_API IWhenCalledInterface { GENERATED_IINTERFACE_BODY() public: UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="SURAXR") int GetPriority() const; UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="SURAXR") void DoAtBeginFrame(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="SURAXR") void DoAtEndFrame(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="SURAXR") void DoAtBeginFrameRT(); UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="SURAXR") void DoAtEndFrameRT(); }; UCLASS(Blueprintable, BlueprintType) class SURAXR_API AWhenCalled : public AActor, public IWhenCalledManagerInterface { GENERATED_BODY() public: // Sets default values for this actor's properties AWhenCalled(); // Begin IWhenCalledManagerInterface // Return: 0 on success; -1 on null Handler; 1 on Handler exists; 2 on Priority conflicts. UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="SURAXR") int AddHandler(const TScriptInterface<IWhenCalledInterface>& Handler); virtual int AddHandler_Implementation(const TScriptInterface<IWhenCalledInterface>& Handler) override; virtual void BindDelegates() override; // End IWhenCalledManagerInterface protected: // Called when the game starts or when spawned virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; public: // Called every frame virtual void Tick(float DeltaTime) override; private: // Begin IWhenCalledManagerInterface UPROPERTY() TMap<int, TScriptInterface<IWhenCalledInterface>> Manager; // End IWhenCalledManagerInterface }; //////// implementation file ////// // Fill out your copyright notice in the Description page of Project Settings. #include "WhenCalled.h" UWhenCalledInterface::UWhenCalledInterface(class FObjectInitializer const &ObjectInitializer) :Super(ObjectInitializer) {} UWhenCalledManagerInterface::UWhenCalledManagerInterface(class FObjectInitializer const &ObjectInitializer) :Super(ObjectInitializer) {} // Sets default values AWhenCalled::AWhenCalled() { // 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; } int AWhenCalled::AddHandler_Implementation( const TScriptInterface<IWhenCalledInterface>& Handler ) { UObject* Object = Handler.GetObject(); IWhenCalledInterface* IHandler = Cast<IWhenCalledInterface>(Object); if (Object || IHandler) { if (Manager.FindKey(Handler) != nullptr) { return 1; // Handler exists } TArray<int> Keys; Manager.GetKeys(Keys); for (int k: Keys) { int Prior = IHandler == nullptr? IWhenCalledInterface::Execute_GetPriority(Object) : IHandler->GetPriority(); if (k == Prior) { return 2; // Priority conflicts. } } int Prior = IHandler == nullptr ? IWhenCalledInterface::Execute_GetPriority(Object) : IHandler->GetPriority(); Manager.Add(Prior, Handler); Manager.KeyStableSort([](int A, int B) { return A < B; }); return 0; } return -1; } void AWhenCalled::BindDelegates( ) { FCoreDelegates::OnBeginFrame.AddWeakLambda(this, [this]() { for (auto& iter : Manager) { UObject* Object = iter.Value.GetObject(); if (Object) { IWhenCalledInterface::Execute_DoAtBeginFrame(Object); continue; } IWhenCalledInterface* IHandler = Cast<IWhenCalledInterface>(Object); if (IHandler) { IHandler->DoAtBeginFrame(); continue; } } }); FCoreDelegates::OnEndFrame.AddWeakLambda(this, [this]() { for (auto& iter : Manager) { UObject* Object = iter.Value.GetObject(); if (Object) { IWhenCalledInterface::Execute_DoAtEndFrame(Object); continue; } IWhenCalledInterface* IHandler = Cast<IWhenCalledInterface>(Object); if (IHandler) { IHandler->DoAtEndFrame(); continue; } } }); /*FCoreDelegates::OnBeginFrameRT.AddWeakLambda(this, [this]() { for (auto& iter : Manager) { IWhenCalledInterface* IHandler = Cast<IWhenCalledInterface>(iter.Value); if (IHandler) { IHandler->DoAtBeginFrameRT(); } } }); FCoreDelegates::OnEndFrameRT.AddWeakLambda(this, [this]() { for (auto& iter : Manager) { IWhenCalledInterface* IHandler = Cast<IWhenCalledInterface>(iter.Value); if (IHandler) { IHandler->DoAtEndFrameRT(); } } });*/ } // Called when the game starts or when spawned void AWhenCalled::BeginPlay() { Super::BeginPlay(); BindDelegates(); } void AWhenCalled::EndPlay( const EEndPlayReason::Type EndPlayReason ) { Super::EndPlay(EndPlayReason); } // Called every frame void AWhenCalled::Tick(float DeltaTime) { Super::Tick(DeltaTime); }