[UE4]C++定义接口Interface,C++/蓝图使用Interface

参考链接:https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Interfaces/

C++定义Interface

ReactToTriggerInterface.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "ReactToTriggerInterface.generated.h"

// This class does not need to be modified.
// Blueprintable:将该类公开为可用于蓝图中的变量的类型。
UINTERFACE(MinimalAPI, Blueprintable)
class UReactToTriggerInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 *
 */
class CMYGAME_API IReactToTriggerInterface
{
	GENERATED_BODY()

		// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

	// 此接口可以在接口的.cpp中定义一个默认的实现,并且只能在C++中重写
	virtual bool ReactToTrigger();

	// 只能在蓝图中重写
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
		void TouchedToTrigger();

	// 能在 蓝图 与 C++ 中重写。可以在接口的.cpp文件中实现一个默认的 接口函数。但是这里没有实现
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		bool SteppedToTrigger();

	// 能在 蓝图 与 C++ 中重写。可以在接口的.cpp文件中实现一个默认的 接口函数。
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		void BumpTntoToTrigger();
	virtual void BumpTntoToTrigger_Implementation(); // 在接口中实现一个默认的 接口函数

	// 能在 蓝图 与 C++ 中重写。可以在接口的.cpp文件中实现一个默认的 接口函数。
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		void Test_2(int32 gold);
	virtual void Test_2_Implementation(int32 gold); // 在接口中实现一个默认的 接口函数
};

ReactToTriggerInterface.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "ReactToTriggerInterface.h"

// Add default functionality here for any IReactToTriggerInterface functions that are not pure virtual.

bool IReactToTriggerInterface::ReactToTrigger()
{
	UE_LOG(LogTemp, Log, TEXT("IReactToTriggerInterface::ReactToTrigger()"));
	return true;
}

void IReactToTriggerInterface::BumpTntoToTrigger_Implementation()
{
	UE_LOG(LogTemp, Log, TEXT("IReactToTriggerInterface::BumpTntoToTrigger_Implementation()"));
}

void IReactToTriggerInterface::Test_2_Implementation(int32 gold)
{
	UE_LOG(LogTemp, Log, TEXT("IReactToTriggerInterface::Test_2_Implementation()"));
}

C++使用接口

Trap.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ReactToTriggerInterface.h"
#include "Trap.generated.h"

UCLASS()
class CMYGAME_API ATrap : public AActor,public IReactToTriggerInterface
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATrap();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	/* ---------------------------------------- */
	// C++ 实现接口函数
	virtual bool ReactToTrigger() override;
	/* ---------------------------------------- */

	/* ---------------------------------------- */
	// 实现接口函数
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		bool SteppedToTrigger();
	virtual bool SteppedToTrigger_Implementation() override;
	/* ---------------------------------------- */

	/* ---------------------------------------- */
	// 实现接口函数,同时这个函数有默认的实现,如果这里不重新实现,则调用时调用默认的实现
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		void BumpTntoToTrigger();
	virtual void BumpTntoToTrigger_Implementation() override; // 实现接口函数
	/* ---------------------------------------- */

	/* ---------------------------------------- */
	// 实现接口函数,同时这个函数有默认的实现,如果这里不重新实现,则调用时调用默认的实现
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
		void Test_2(int32 gold);
	//virtual void Test_2_Implementation(int32 gold) override; //实现接口函数 这里注释掉了
	/* ---------------------------------------- */

	UPROPERTY(EditAnywhere)
	UStaticMeshComponent* StMeshComponent;
};

Trap.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Trap.h"

// Sets default values
ATrap::ATrap()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	RootComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RootComponent"));
	StMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StMeshComponent"));
	//RootComponent = StMeshComponent;
	StMeshComponent->SetupAttachment(RootComponent);
}

// Called when the game starts or when spawned
void ATrap::BeginPlay()
{
	Super::BeginPlay();

	ReactToTrigger(); // 调用纯C++接口
	//SteppedToTrigger();
	//BumpTntoToTrigger();
	//Test_2(99);
	this->Execute_TouchedToTrigger(this); // 调用接口,这个接口时纯蓝图接口,在蓝图中实现
	this->Execute_SteppedToTrigger(this); // 调用接口,这个接口可以在蓝图中重写
	this->Execute_BumpTntoToTrigger(this); // 调用接口,这个接口可以在蓝图中重写
	this->Execute_Test_2(this,99); // 调用接口,这个接口可以在蓝图中重写
}

// Called every frame
void ATrap::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

bool ATrap::ReactToTrigger()
{
	UE_LOG(LogTemp, Log, TEXT("ATrap::ReactToTrigger()"));
	return true;
}

bool ATrap::SteppedToTrigger_Implementation()
{
	UE_LOG(LogTemp, Log, TEXT("ATrap::SteppedToTrigger_Implementation()"));
	return true;
}

void ATrap::BumpTntoToTrigger_Implementation()
{
	UE_LOG(LogTemp, Log, TEXT("ATrap::BumpTntoToTrigger_Implementation()"));
}

// void ATrap::Test_2_Implementation(int32 gold)
// {
// 	UE_LOG(LogTemp, Log, TEXT("ATrap::Test_2_Implementation()"));
// }

编辑器运行输出

LogTemp: ATrap::ReactToTrigger()
LogTemp: ATrap::SteppedToTrigger_Implementation()
LogTemp: ATrap::BumpTntoToTrigger_Implementation()
LogTemp: IReactToTriggerInterface::Test_2_Implementation()

确定类是否实现了接口

参考链接:https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Interfaces/

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

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

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

IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // 如果OriginalObject实现了UReactToTriggerInterface,则ReactingObject将为非空。

转换到其他虚幻类型

IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // 如果接口被实现,则ReactingObject将为非空。

ISomeOtherInterface* DifferentInterface = Cast<ISomeOtherInterface>(ReactingObject); // 如果ReactingObject为非空而且还实现了ISomeOtherInterface,则DifferentInterface将为非空。

AActor* Actor = Cast<AActor>(ReactingObject); // 如果ReactingObject为非空且OriginalObject为AActor或AActor派生的类,则Actor将为非空。

在C++中遍历对象并调用接口

知识点:UE4 迭代器,遍历对象并调用接口。

TestInterfaceActor.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestInterfaceActor.generated.h"

UCLASS()
class CMYGAME_API ATestInterfaceActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATestInterfaceActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// 测试 UE4 迭代器,接口,获取关卡内对象
	UFUNCTION()
	void CallInterface();
};

TestInterfaceActor.cpp文件

// Fill out your copyright notice in the Description page of Project Settings.


#include "TestInterfaceActor.h"
#include "Trap.h"
#include <EngineUtils.h>

// Sets default values
ATestInterfaceActor::ATestInterfaceActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void ATestInterfaceActor::BeginPlay()
{
	Super::BeginPlay();

	// 测试接口
	CallInterface();
}

// Called every frame
void ATestInterfaceActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// 测试 UE4 迭代器,接口,获取关卡内对象
void ATestInterfaceActor::CallInterface()
{
	// UE4 迭代器TActorIterator
	//TActorIterator<T> actorIt = TActorIterator<T>(GetWorld());
	// 获取关卡里面所有的 ATrap 对象
	TActorIterator<ATrap> actorIt = TActorIterator<ATrap>(GetWorld(),ATrap::StaticClass());
	for (actorIt; actorIt; ++actorIt)
	{
		if (!actorIt)
		{
			continue;
		}
		ATrap* trap = *actorIt;
		//判断ATrap类是否实现了 UReactToTriggerInterface 接口,这里传入 UReactToTriggerInterface 而非 IReactToTriggerInterface
		bool isImplement = trap->GetClass()->ImplementsInterface(UReactToTriggerInterface::StaticClass());
		if (isImplement)
		{
			// 转换为 IReactToTriggerInterface 接口
			IReactToTriggerInterface* inter = Cast<IReactToTriggerInterface>(trap); 

			inter->Execute_TouchedToTrigger(trap); // 调用接口,这个接口时纯蓝图接口,只能在蓝图中实现
			inter->Execute_SteppedToTrigger(trap); //调用接口,蓝图可覆盖接口
			inter->Execute_BumpTntoToTrigger(trap); //调用接口,蓝图可覆盖接口
			inter->Execute_Test_2(trap, 99);//调用接口,蓝图可覆盖接口
			inter->ReactToTrigger();//调用接口,纯C++接口
		}
	}

	// -- GetAllActorsOfClass
	//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("------------------ GetAllActorsOfClass"));
	//TArray<AActor*> ArryActors;
	//UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATrap::StaticClass(), ArryActors);
	//for (int32 i = 0; i < ArryActors.Num(); i++)
	//{
	//	Cast<ATrap>(ArryActors[i])->Execute_TouchedToTrigger(ArryActors[i]); // 调用接口,这个接口时纯蓝图接口,只能在蓝图中实现
	//	Cast<ATrap>(ArryActors[i])->Execute_SteppedToTrigger(ArryActors[i]); //调用接口,蓝图可覆盖接口
	//	Cast<ATrap>(ArryActors[i])->Execute_BumpTntoToTrigger(ArryActors[i]); //调用接口,蓝图可覆盖接口
	//	Cast<ATrap>(ArryActors[i])->Execute_Test_2(ArryActors[i], 99);//调用接口,蓝图可覆盖接口
	//	Cast<ATrap>(ArryActors[i])->ReactToTrigger();//调用接口,纯C++接口
	//}
}

蓝图使用C++定义的接口 方法1

1.首先新建一个蓝图 Bp_TestInterface 继承与Actor

2.蓝图继承 ReactToTriggerInterface 接口

3.实现ReactToTriggerInterface 的接口函数,并调用,如下图

 输出结果:

蓝图使用C++定义的接口 方法2

1.首先新建一个蓝图 BP_Trap1_Blueprint 继承与C++ Trap类(上面的C++类,实现了ReactToTriggerInterface接口)

2.在蓝图中重写ReactToTriggerInterface的接口

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值