接口

创建和实现接口的引用。

Windows
MacOS
Linux

接口类有助于确保一组(可能)不相关的类实现一组通用函数。在某些游戏功能可能被大量复杂而不同的类共享的情况下,这非常有用。例如,某个游戏可能有这样一个系统,依靠该系统输入一个触发器体积可以激活陷阱、警告敌人或向玩家奖励点数。这可以通过针对陷阱、敌人和点数奖励器执行“ReactToTrigger”函数来实现。然而,陷阱可能派生自“AActor”,敌人可能派生自专门的“APawn”或“ACharacter”子类,点数奖励可能派生自“UDataAsset”。所有这些类都需要共享功能,但它们没有除“UObject”之外的共同上级。在这种情况下,推荐使用接口。

接口声明

声明接口类与声明普通的虚幻类相似,但仍有两个主要区别。首先,接口类使用UINTERFACE宏而不是UCLASS宏,且直接从“UInterface”而不是“UObject”继承。

UINTERFACE([specifier, specifier, ...], [meta(key=value, key=value, ...)])
class UClassName : public UInterface
{
    GENERATED_BODY()
};

其次,UINTERFACE类不是实际的接口;它是一个空白类,它的存在只是为了向虚幻引擎反射系统确保可见性。将由其他类继承的实际接口必须具有相同的类名,但是开头字母“U”必须改为“I”。

在您的.h文件(例如“ReactToTriggerInterface.h”)中:

#pragma once

#include "ReactToTriggerInterface.generated.h"

UINTERFACE(Blueprintable)
class UReactToTriggerInterface : public UInterface
{
    GENERATED_BODY()
};

class IReactToTriggerInterface
{    
    GENERATED_BODY()

public:
    /** 对激活该对象的触发器体积做出响应。如果响应成功,返回“真(true)”。*/
    UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="Trigger Reaction")
    bool ReactToTrigger() const;
};

函数可以直接写入.h文件中,且写入操作通常是在函数不执行任何操作时(默认)或者具有诸如返回false、零、空白字符串(或类似内容)等简单行为时执行。更为复杂的函数可以写入.cpp文件中以缩短编译时间,而且系统也支持纯虚拟函数。虽然我们的示例函数很简单而且按理可以写入.h文件中,但是我们选择将其写入.cpp文件中。您的.cpp文件(例如“ReactToTriggerInterface.cpp”)现在应包含以下内容:

#include "ReactToTriggerInterface.h"

bool IReactToTriggerInterface::ReactToTrigger() const
{
    return false;
}

“U-prefixed”类不需要构造函数或任何其他函数,而“I-prefixed”类将包含所有接口函数,且此类实际上将被您的其他类继承。

如果您想要让蓝图实现此接口,则需要“Blueprintable”说明符。

接口说明符

接口说明符

含义

“BlueprintType”

将该类公开为可用于蓝图中的变量的类型。

“DependsOn=(ClassName1, ClassName2, ...)”

所有列出的类都将在该类之前编译。ClassName必须在同一个(或上一个)包中指定一个类。多个依赖性类可以使用以逗号分隔的单个“DependsOn”行来指定,也可以使用单个“DependsOn”行为每个类指定。当一个类使用在另一个类中声明的结构体或枚举时,这一点非常重要,因为编译器只知道它已经编译的类中的内容。

“MinimalAPI”

仅导致该类的类型信息被导出以供其他模块使用。您可以向该类投射,但不能调用该类的函数(内联方法除外)。对于不需要其所有函数在其他模块中均可供访问的类,通过不导出这些类的所有内容,这可以缩短编译时间。

在C++中实现接口

若要在一个新的类中使用您的接口,只需从“前缀为I(I-prefixed)”接口类继承(除了您正在使用的任何基于“UObject”的类)即可。

class ATrap : public AActor, public IReactToTriggerInterface
{
    GENERATED_BODY()

public:
    virtual bool ReactToTrigger() const override;
};

确定给定的类是否实现了接口

为了与实现接口的C++和蓝图类兼容,可以使用以下任意一个函数:

bool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UReactToTriggerInterface::StaticClass()); // 如果OriginalObject实现了UReactToTriggerInterface,则bisimplemated将为true。
IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // 如果OriginalObject实现了UReactToTriggerInterface,则ReactingObject将为非空。

尝试在“U为前缀(U-prefixed)”类上使用“投射(Cast)”将失败,而“StaticClass”函数在“I为前缀(I-prefixed)”类中没有实现,将无法编译。

投射到其他虚幻类型

虚幻引擎的投射系统支持从一个接口投射到另一个接口,或者在适当的情况下,从一个接口投射到一个虚幻类型。

IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // 如果接口被实现,则ReactingObject将为非空。
ISomeOtherInterface* DifferentInterface = Cast<ISomeOtherInterface>(ReactingObject); // 如果ReactingObject为非空而且还实现了ISomeOtherInterface,则DifferentInterface将为非空。
AActor* Actor = Cast<AActor>(ReactingObject); // 如果ReactingObject为非空且OriginalObject为AActor或AActor派生的类,则Actor将为非空。

蓝图可实现类

如果您想要蓝图能够实现此接口,则必须使用“Blueprintable”元数据说明符。蓝图类要覆盖的每个接口函数都必须是“BlueprintNativeEvent”或“BlueprintImplementableEvent”。标记为“BlueprintCallable”的函数仍然可以被调用,但不能被覆盖。您将无法从蓝图访问所有其他函数。

标签
Select Skin
Light
Dark

欢迎来到全新虚幻引擎4文档站!

我们正在努力开发新功能,包括反馈系统,以便您能对我们的工作作出评价。但它目前还未正式上线。如果您对此页面有任何意见与在使用中遭遇任何问题,请前往文档反馈论坛告知我们。

新系统上线运行后,我们会及时通知您的。

发表反馈意见