程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 介紹Unreal Engine 4中的接口(Interface)使用C++和藍圖,unrealengine

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

編輯:C++入門知識

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


這個教程是從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

 

參考文章:

  • Interfaces And Blueprints
  • Interfaces in C++
  • Expose an interface to blueprint

     

     

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved