介紹Unreal Engine 4中的接口(Interface)使用C++和藍圖

這個教程是從UE4 Wiki上整理而來.git

在C++中直接使用Interface你們應該很熟悉。只是簡單先定義一個個有虛函數的基類,而後在子類中實現相應的虛函數。像這樣的虛函數的基類通常概念上叫接口。那接下來看看UE4中怎樣在C++中定義接口的。github

.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();
 
};

.cppide

#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,這樣藍圖就能夠實現這個接口了,藍圖中就像普通事件同樣實現。ui

.hspa

#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;
};

 

.cppcode

#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的方式再包裝一層,可是我以爲這不是很好。blog

在藍圖中實現Event接口:

以前的NPCActor由於已經繼承了ITargetInterface因此,你在藍圖編輯器裏能夠直接實現OnInteract接口事件。

那若是你純藍圖的Actor怎麼辦。

進入藍圖編輯點Class Settings

3402568203

在Interfaces面板點Add加入Target Interface就行了

3523847589

 

那怎調用這個藍圖實現的接口在C++裏?

看下面的代碼

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

 

參考文章:

相關文章
相關標籤/搜索