UE5.3 C++ 接口初步使用

发布于:2025-09-09 ⋅ 阅读:(20) ⋅ 点赞:(0)

在虚幻引擎中实现蓝图接口 | 虚幻引擎 5.6 文档 | Epic Developer Community

虚幻引擎中的接口 | 虚幻引擎 5.6 文档 | Epic Developer Community

一.类向导里创建Interface

二.创建ReactToTriggerInterface接口

1.U类负责反射,I类负责逻辑。

U类负责反射,因为反射都需要继承自UObject。在I类里面实现,是为了防止菱形继承。

反射系统是选择加入的,只有主动标记的类型、属性、方法会被反射系统追踪, UnrealHeaderTool 会收集这些信息,生成用于支持反射机制的C++代码,然后再编译工程。 UObject是反射系统的核心。 每一个继承UObject且支持反射系统的类型都有一个相应的UClass,或者它的子类,UClass中包含了该类的描述信息。

2.声明定义

BlueprintNativeEvent,用了虚函数实现的方式。在接口里可以实现 C++ 默认接口。也可以不实现。实现的话,需要加virtual和_Implementation,先声明再定义。但不建议BlueprintNativeEvent的接口,直接在内部定义。因为它一定会被,继承的类重载,哪怕代码一摸一样,你也要抄一份过去,他最终调用的是继承接口的派生类的,这一点与C++思想一样。C++的接口是定义纯虚函数 = 0,在派生类必须重载。在接口的定义BlueprintNativeEvent的函数没用意义。也就是BumpTntoToTrigger_Implementation()是没啥意义的。

有一个方式可以用接口默认方法,但是那个不安全。不建议使用,就是不声明BumpTntoToTrigger所有相关的函数。但却使用这个接口。无论是官方文档还是源代码报错的地方都不建议这样做。

virtual void BumpTntoToTrigger_Implementation(); // 在接口中实现一个默认的 接口函数
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "ReactToTriggerInterface.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UReactToTriggerInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class GWXPJ_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(); // 在接口中实现一个默认的 接口函数

	
};

#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()"));
}

3.然后用一个Actor类继承,并用各种方式重写。

// 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 GWXPJ_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;

	//接口
	virtual bool ReactToTrigger() override;
	/* ---------------------------------------- */

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

	/* ---------------------------------------- */
	// 实现接口函数
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void BumpTntoToTrigger();
	virtual void BumpTntoToTrigger_Implementation(); // 实现接口函数
	/* ---------------------------------------- */



	UPROPERTY(EditAnywhere)
	UStaticMeshComponent* StMeshComponent;
};
#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();
	
	//C++ 里调用接口
	ReactToTrigger(); // 调用纯C++接口
	//SteppedToTrigger();
	//SteppedToTrigger_Implementation();
	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()"));
}

4.再通过测试是否实现接口,并调用接口

// 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 GWXPJ_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();
};
// 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);

}

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++接口
		}
	}
}

也可以继承自蓝图后,在蓝图里重写后调用


网站公告

今日签到

点亮在社区的每一天
去签到