参考链接: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的接口