在Epic官方的塔防游戏源码中看到的关于Interface用法,写法非常绕。。这里做下笔记。
1,先建一个空的C++工程,名字叫做TestProj。
2,现在Editor中新建一个空的C++ class(父类选择None即可,论坛上说父类继承Object也可以)。创建完后生成的内容是这样的:
MyInterface.h原始代码
#pragma once
/**
*
*/
class TESTPROJ_API MyInterface
{
public:
MyInterface();
~MyInterface();
};
将其改成以下内容(目前版本貌似只能手动改,官方文档上也是要求手动改。。),这里注意下:上面是UMyInterface,下面是IMyInterface。
后面的代码都要特别注意下,因为这个U和I开头的类型名会交替出现,比较蛋疼。。
这里为了演示,在IMyInterface中添加了两个函数,一个是虚函数ToString(),一个是UE4模版函数。
注意里面的宏定义,上面是GENERATED_UINTERFACE_BODY,下面是GENERATED_IINTERFACE_BODY。
MyInterface.h修改后代码
#pragma once
#include "MyInterface.generated.h"
/**
*
*/
UINTERFACE()
class UMyInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
};
class IMyInterface
{
GENERATED_IINTERFACE_BODY()
virtual FString ToString();
//Interface中函数的说明符也可以不是BlueprintNativeEvent,这里仅演示
UFUNCTION(BlueprintNativeEvent)
void OnInputHoldReleased(float DownTime);
};
然后MyInterface.cpp文件的内容也要全部改掉,这里的构造函数必须定义成:UMyInterface(const class FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer),且实现其他函数时,必须用IMyInterface,
改后的内容如下,MyInterface.cpp:
#include "TestProj.h"
#include "MyInterface.h"
UMyInterface::UMyInterface(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
FString IMyInterface::ToString()
{
return "IMyInterface::ToString()";
}
3,新建一个常规的自定义Actor,并继承IMyInterface,在文件中不能自己定义构造函数,取而代之的是一个宏定义:GENERATED_UCLASS_BODY。除非确认无需调用父类MyInterface的构造函数,那么可以使用GENERATED_BODY,并定义常规的构造函数。
其中重写父类OnInputHoldReleased() 方法时,添加了_Implementation后缀,这是因为使用BlueprintNativeEvent说明符,若要实现BlueprintNativeEvent的函数,函数名必须添加_Implementation后缀。
MyActor.h
#pragma once
#include "GameFramework/Actor.h"
#include "MyInterface.h"
#include "MyActor.generated.h"
UCLASS()
class TESTPROJ_API AMyActor : public AActor, public IMyInterface
{
GENERATED_UCLASS_BODY()
virtual FString ToString() override;
virtual void OnInputHoldReleased_Implementation(float DownTime) override;
};
子类实现时构造函数也需要用同样的模版格式:AMyActor(const class FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer),
MyActor.cpp
#include "TestProj.h"
#include "MyActor.h"
AMyActor::AMyActor(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
FString AMyActor::ToString()
{
return "AMyActor::ToString()";
}
void AMyActor::OnInputHoldReleased_Implementation(float TimeDown)
{
}
4,调用UFUNCTION和普通函数调用方法不同,调用UFUNCTION类型的接口函数时,要通过“接口名::Execute_函数名(子类对象实例, 参数......)”,例如下面:IMyInterface::Execute_OnInputHoldReleased(Actor, 0.5f);
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
//ClientSetViewTarget();
//1,调用蓝图函数
AActor* const Actor = NULL; //这里假设actor不为NULL,为演示方便没有实现获取MyActor的逻辑
if (Actor && Actor->GetClass()->ImplementsInterface(UMyInterface::StaticClass()))
{
IMyInterface::Execute_OnInputHoldReleased(Actor, 0.5f);
}
//2,调用普通函数
IMyInterface* myInterface = Cast<IMyInterface>(Actor);
FString str = myInterface->ToString();
}
其他参考:
wiki:Interfaces And Blueprints
https://wiki.unrealengine.com/Interfaces_And_Blueprints
Interfaces in C++
https://wiki.unrealengine.com/Interfaces_in_C%2B%2B#The_Interface
官方文档:Interfaces
https://docs-origin.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Interfaces/index.html
Calling Interface Functions In C++
https://answers.unrealengine.com/questions/250263/calling-interface-functions-in-c.html
How to create an interface in C++
https://answers.unrealengine.com/questions/186606/how-to-create-an-interface-in-c.html