這個教程是從UE4 Wiki上整理而來.
在C++中直接使用Interface大家應該很熟悉。只是簡單先定義一個個有虛函數的基類,然後在子類中實現相應的虛函數。像這樣的虛函數的基類一般概念上叫接口。那接下來看看UE4中怎樣在C++中定義接口的。
.h
#pragma once #include "TargetInterface.generated.h" UINTERFACE(MinimalAPI) class UTargetInterface : public UInterface { GENERATED_UINTERFACE_BODY() }; class ITargetInterface{ GENERATED_IINTERFACE_BODY() public: UFUNCTION(BlueprintImplementableEvent, meta=(FriendlyName = "On Interact")) void OnInteract(bool bNewOpen); virtual float GetHealth(); };
.cpp
#include "YourProject.h" #include "TargetInterface.h" UTargetInterface::UTargetInterface(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{ } // Give GetHealth a default implementation float ITargetInterface::GetHealth(){ return 0.0f; }
首先定義一個UTargetInterface這個是給引擎內部模塊用的,一般不會用到,但是要定義。
ITargetInterface是你要使用的類,你要聲明的函數接口都放在這裡面。如果是定義函數給C++用的,那麼你就直接按標准的C++聲明一個虛函數就OK了,然後你要實現這個接口的子類繼承ITargetInterface實現GetHealth函數就可以了。如果是給Blueprint用的,就要在函數前一行聲明的UFUNCTION內加上BlueprintImplementableEvent,這樣藍圖就可以實現這個接口了,藍圖中就像普通事件一樣實現。
.h
#pragma once #include "GameFramework/Actor.h" #include "TargetInterface.h" #include "NPCActor.generated.h" UCLASS() class MMWORLD_API NPCActor
: public AActor , public ITargetInterface
{ GENERATED_BODY() public: AInteractiveTargetActor();
virtual float GetHealth() override;
protected:
float Health;
};
.cpp
#include "YourProject.h" #include "NPCActor.h" NPCActor::NPCActor() { Health = 100.0f; } float NPCActor::GetHealth() { return Health; }
在C++代碼中這樣調用.如果是你知道Actor類的實際類型,直接調用就可以了。你不知道Actor的類型時候Interface才有實際的用處。
auto MyInterface = Cast<ITargetInterface>(ActorInstance); if (MyInterface) { float ActorHealth = MyInterface->GetHealth(); }
但是這樣的接口藍圖中是無法使用的,藍圖完全無法知道它的存在。你可以再用Blueprint Function Library的方式再包裝一層,但是我覺得這不是很好。
在藍圖中實現Event接口:
之前的NPCActor因為已經繼承了ITargetInterface所以,你在藍圖編輯器裡可以直接實現OnInteract接口事件。
那如果你純藍圖的Actor怎麼辦。
進入藍圖編輯點Class Settings
if (ActorInstance->GetClass()->ImplementsInterface(ITargetInterface::StaticClass())) { ITargetInterface::Execute_OnInteract(ActorInstance, true); }
ActorInstance->GetClass()->ImplementsInterface(ITargetInterface::StaticClass())) 是用來判斷這個Actor是否實現了TargetInterface,不管是在藍圖還是C++中都可以正確的判斷(但是只有BlueprintImplementableEvent和BlueprintNativeEvent(這個後面再介紹)的函數才可以被藍圖實現)。Execute_OnInteract執行藍圖事件,第一個參數是UObject對象(接口調用的執行目標對象),後面的參數就是OnInteract函數的參數。這個函數是UHT自動生成的。其實這個函數本質上就是調用的UObject的ProcessEvent,具體你可以看生成的代碼。(你到這個目錄下的文件看看就知道了,Yourproject\Intermediate\Build\Win64\Inc\Yourproject\Yourproject.generated.cpp,Yourproject是你的項目名稱)
最後一個問題,那如果想要這個函數接口既可以被C++實現又要被Blueprint實現怎麼辦?
你只要簡單的把BlueprintImplementableEvent改成BlueprintNativeEvent就可以了。
.h
#pragma once #include "InteractionsInterface.generated.h" UINTERFACE() class MMWORLD_API UInteractionsInterface : public UInterface { GENERATED_UINTERFACE_BODY() }; class MMWORLD_API IInteractionsInterface { GENERATED_IINTERFACE_BODY() public: UFUNCTION(BlueprintNativeEvent) void SwitchTurned(bool bNewOnOrOff, int32 CustomParam); };
.cpp
#include "MMWorld.h" #include "InteractionsInterface.h" UInteractionsInterface::UInteractionsInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { }
實現的Actor
.h
#pragma once #include "GameFramework/Actor.h" #include "InteractionsInterface.h" #include "InteractiveTargetActor.generated.h" UCLASS() class MMWORLD_API AInteractiveTargetActor : public AActor , public IInteractionsInterface { GENERATED_BODY() public: AInteractiveTargetActor(); virtual void SwitchTurned_Implementation(bool bNewOnOrOff, int32 CustomParam) override; UFUNCTION(BlueprintImplementableEvent, Category = Interactive) void SwitchAllTurnedOnOrOff(bool bOnOrOff); UFUNCTION(BlueprintCallable, Category = Interactive) bool IsSwitchTurned(int32 Index); UFUNCTION(BlueprintCallable, Category = Interactive) bool IsSwitchAllTurnedOn(); UFUNCTION(BlueprintCallable, Category = Interactive) bool IsSwitchAllTurnedOff(); protected: UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (ClampMin = "1", ClampMax = "32", UIMin = "1", UIMax = "32")) int32 NeedSwitchTurnedNum; uint32 SwitchTurnedStates; };
SwitchTurned在C++中要實現的函數是virtual void SwitchTurned_Implementation(bool bNewOnOrOff, int32 CustomParam) override; (BlueprintNativeEvent的函數名字_Implementation)。這個函數也是UHT自動生成的。
如果是你在Blueprint中是實現了SwitchTurned接口,那麼C++的實現就會被覆蓋隱藏掉。
那如果你的藍圖又要掉用C++接口實現怎麼辦?
UE4中沒有直接實現這樣的機制。但是你可以把SwitchTurned_Implementation實現提取出來一個新函數,然後把這個函數定義成UFUNCTION(BlueprintCallable, Category = Interactive),然後在藍圖中調用這個函數就解決了。
好了就介紹到這裡,第一次寫關於UE4的東西,不對的地方希望大家指正。希望這個對你有幫助。
參考例子:
https://github.com/henrya2/MMWorld
參考文章: