文章

UE5中UInterface使用备忘

UInterface这个系统其实UE4就有,只是一些相关的东西每次都会不小心踩坑。

接口的官方文档是这个: Unreal Interfaces

指针容器

官方有提供一些接口的指针容器,可以更方便的对接口指针进行存储,比保存UObject指针然后每次检查和转换方便很多。

TWeakInterfacePtr

弱指针,不能作为蓝图属性。

TWeakInterfacePtr<IMyAwsomeInteface> MyPtr;

但是有提供TWeakObjectPtr一样的IsValid封装,在C++逻辑中比较实用。

TScriptInterface

可以作为蓝图属性存在。

TScriptInterface<IMyAwsomeInteface> MyPtr;

目前无法兼容在蓝图中继承的情况。可以参照官方的类注释

This type is only useful with native interfaces, UClass::ImplementsInterface should be used to check for blueprint interfaces.

MustImplement

可以通过MustImplement标签来要求指针必须实现接口

UPROPERTY(meta=(MustImplement ="/Script/MyAwusomeModule.MyAwsomeInteface"))
TObjectPtr<AActor> MyActor;

即便是在蓝图中实现的接口也能兼容,对于从关卡中选择物品的情况比较有用,可以有效的防止选错。

指针转换

通常情况下,在需要做指针转换时,有以下三种方法

/** 如果OriginalObject实现了UMyAwsomeInterface,则bisimplemated将为true。*/
bool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UMyAwsomeInterface::StaticClass()); 

/** 如果OriginalObject实现了UReactToTrigger,bIsImplemented将为true。 */
bIsImplemented = OriginalObject->Implements<UMyAwsomeInterface>(); 

/** 如果OriginalObject实现了UMyAwsomeInterface,则RCastedInterfaceObject将为非空。 */
IMyAwsomeInterface* CastedInterfaceObject = Cast<IMyAwsomeInterface>(OriginalObject);

按照官方的说法,这三个接口是等价的。 但是实际情况是,如果接口是在蓝图中继承的话,会出现:Cast<IMyAwsomeInteface>(IterActor)返回空,但是IterActor->Implements<UMyAwsomeInteface>()却成功的情况。

如果制作逻辑的时候没有留意到的话,很可能会出现一些不在预期中的情况。

安全的方法

以下的调用方法是基本安全的:

  1. 使用Implements检查指针是否实现了接口
  2. IMyAwsomeInteface::Execute_MyAwsomeFunction

指针自动转换

帮助类指针自动转换并不会提供一个绕过IMyAwsomeInteface::Execute_的机会,当前其实和手动Cast然后赋值给帮助类是一样的。

基本可以将蓝图实现接口和直接在代码中继承使用的接口当作两种情况来看待:

将UInterface当作一种提供转换帮助类的C++层接口封装的时候,使用起来会比较随意。

如果接口会在蓝图中使用,则基本上使用IMyAwsomeInteface::Execute_系列会比较安全。

DoesImplementInterface

UKismetSystemLibrary::DoesImplementInterface是官方提供的帮助类,其实是对ImplementsInterface的封装,则基本可以等效对待。