`
aigo
  • 浏览: 2538335 次
  • 性别: Icon_minigender_1
  • 来自: 宜昌
社区版块
存档分类
最新评论

[UE4]Interface用法:GENERATED_IINTERFACE_BODY

UE4 
阅读更多

在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)
{

}
 【2016-09-23更新】
最新版的UE4已经不支持这种写法,会提示编译错误:
 error C2084: function 'AMyActor::AMyActor(const FObjectInitializer &)' already has a body

最新版本写法是:如果要构造函数,那么构造函数不用带参数且需要在头文件中定义无参构造函数
AMyActor::AMyActor()
{
}
 

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();
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics