詞義廣泛,用來陳述功能,選項,與其他程式結構進行溝通的方式。介面抽象出了互動結構,提供了兩個未知邏輯互動的便捷性。對於程式設計中,如何更好的設計低耦合程式起到了至關重要的作用。設計者可以在互不關心的情況下,進行友好的程式設計,並且通過介面來完成設計的整合互動。
虛幻引擎中,加入了介面設計,從一定程度上「去掉了」多繼承。介面可以幫助我們解決在不同型別的類之間卻有相同行為的特性。介面的設計增加了程式碼編寫的便捷性。
例如在設計射擊類遊戲時,我們需要子彈與場景中的物體進行互動,場景中的桌椅板凳,角色,怪物(都是獨立的物件)都希望受到子彈的攻擊傷害。那麼子彈在打到目標後要逐一排查,審查目標是否屬於上述的物件!這很麻煩!但是我們可以通過介面,增加上述目標具有受傷的能力。當子彈打到目標時,我只需要檢查目標是否繼承受傷的介面,如果有,則呼叫介面函數即可!
構建介面類:
我們可以直接在虛幻編輯器中繼承介面類,然後完成構建
編寫介面:
實現介面:
繼承I類介面完畢後,可以選擇的將介面中的函數進行定義。如果需要定義,則需要將介面中函數說明是BlueprintNativeEvent的函數進行定義。
注意,不要省略override,函數的返回值,參數列需要和介面的一致
呼叫操作:
呼叫函數,持有繼承介面物件指標,第一步先轉換到I類指標,呼叫Execute_介面函數名,引數第一位需要傳遞原物件指標,後面直接按照原函數引數填入即可
整體程式碼演示:
// TestInterface.h UINTERFACE(MinimalAPI) class UTestInterface : public UInterface { GENERATED_BODY() }; /** * 1、U類中不能去寫介面函數,只能用來檢查是否繼承了介面類 * 2、介面函數,必須寫在I類中,並且必須寫共有域中 * 3、介面函數在介面類中不能進行定義 * */ class MX_API ITestInterface { GENERATED_BODY() // Add interface functions to this class. This is the class that will be inherited to implement this interface. public: // 定義介面函數 UFUNCTION(BlueprintNativeEvent) void Notify_None(); UFUNCTION(BlueprintNativeEvent) int32 Notify_RetVal(); UFUNCTION(BlueprintNativeEvent) int32 Notify_RetVal_Params(int32 Num); }; ///////////////////////////////////////////////////////////// // Actor2.h public: // Called every frame virtual void Tick(float DeltaTime) override; // 實現介面 virtual void Notify_None_Implementation() override; virtual int32 Notify_RetVal_Implementation() override; virtual int32 Notify_RetVal_Params_Implementation(int32 Num) override; // Actor2.cpp void AActor2::Notify_None_Implementation() { UKismetSystemLibrary::PrintString(this, TEXT("----無參無返回值----")); } int32 AActor2::Notify_RetVal_Implementation() { UKismetSystemLibrary::PrintString(this, TEXT("----無參有返回值----")); return 0; } int32 AActor2::Notify_RetVal_Params_Implementation(int32 Num) { UKismetSystemLibrary::PrintString(this, TEXT("----有參有返回值----")); return Num; }void AActor2::Notify_None_Implementation() { UKismetSystemLibrary::PrintString(this, TEXT("----無參無返回值----")); } int32 AActor2::Notify_RetVal_Implementation() { UKismetSystemLibrary::PrintString(this, TEXT("----無參有返回值----")); return 0; } int32 AActor2::Notify_RetVal_Params_Implementation(int32 Num) { UKismetSystemLibrary::PrintString(this, TEXT("----有參有返回值----")); return Num; } ///////////////////////////////////////////////////////// //Actor1.cpp ac2 = GetWorld()->SpawnActor<AActor2>(AActor2::StaticClass()); // 檢查是否繼承了介面 ITestInterface* testInterface = Cast<ITestInterface>(ac2); // 如果繼承了介面,就執行介面函數 if (testInterface) { testInterface->Execute_Notify_None(ac2); testInterface->Execute_Notify_RetVal(ac2); testInterface->Execute_Notify_RetVal_Params(ac2,10); }
測試結果:
包裹介面:
藉助模板類TScriptInterface可以將介面包裹,用於使用UPROPERTY描述,並且可以暴露到藍圖中。使用時同普通介面一樣使用。介面不支援智慧指標的管理,所以需要使用TS類進行管理
UPROPERTY(EditAnywhere)
TScriptInterface<ITestInterface> TestInterface;
藍圖繼承介面:
如果介面在藍圖中被繼承,則需要注意下面的問題
總結:
介面的優缺點:
優點:
缺點: