为什么我在虚幻引擎中的多态性和接口方面遇到问题?

Why am I having trouble with polymorphism and interfaces in Unreal Engine

本文关键字:接口 方面 遇到 问题 多态性 引擎 为什么      更新时间:2023-10-16

我一直在尝试在我的游戏中进行交互,但我做错了什么,我不知道在哪里!我将在下面包含一堆代码并省略不相关的位。

我在引擎中创建接口。生成的类称为IInteract。它只包含一个名为voidInteract(ACharacterBase* Caller(的函数。ACharacterBase只是我项目的默认棋子。这是IInteract的头文件。

#pragma once
#include "STRGZR/Characters/CharacterBase.h"
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interact.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UInteract : public UInterface
{
GENERATED_BODY()
};
/**
* 
*/
class STRGZR_API IInteract
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
void Interact(ACharacterBase* Caller);
};

现在,我创建了另一个名为AInteractable的类,并将IInteract实现到AInteractable中。然后我从接口声明了 Interact(ACharacterBase* Caller(。这是AInteracable的代码。

#pragma once
#include "Interact.h"
#include "STRGZR/Characters/CharacterBase.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Interactable.generated.h"
UCLASS()
class STRGZR_API AInteractable : public AActor, public IInteract
{
GENERATED_BODY()
public: 
// Sets default values for this actor's properties
AInteractable();
protected:
UFUNCTION(BlueprintCallable)
void Interact(ACharacterBase* Caller);
public:
};

这是void Interact(ACharacterBase* Caller(的定义。

#include "Interactable.h"
// Sets default values
AInteractable::AInteractable()
{
}
void AInteractable::Interact(ACharacterBase* Caller)
{
Destroy();
}

我想我的第一个问题是,我应该在哪里使用虚拟覆盖AInteractableIInteract中交互函数的关键字?

现在,我设置了键绑定,以便在按下交互键时调用ACharacterBase中的OnInteract。这是ACharacterBase的代码文件。

#include "GameFramework/CharacterMovementComponent.h"
#include "STRGZR/Interactable/Interact.h"
#include "CharacterBase.h"
// Sets default values
ACharacterBase::ACharacterBase()
{   
LineTraceLength = 2000.f;
}
// Called to bind functionality to input
void ACharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// Set up gameplay key bindings
check(PlayerInputComponent);
// Bind Interact event
PlayerInputComponent->BindAction("Interact", IE_Pressed, this, &ACharacterBase::OnInteract);
}
FHitResult ACharacterBase::LineTraceForward()
{
FHitResult HitResult;
FCollisionQueryParams CollisionQueryParams;
FVector CharacterLocation;
FRotator CharacterRotation;
GetActorEyesViewPoint(CharacterLocation, CharacterRotation);
FVector Start = CharacterLocation;
FVector End = CharacterLocation + (CharacterRotation.Vector() * LineTraceLength);

ActorLineTraceSingle(HitResult, Start, End, ECC_Visibility, CollisionQueryParams);
return HitResult;
}
void ACharacterBase::OnInteract()
{
AActor* InteractedActor = LineTraceForward().GetActor();
IInteract* Interface = Cast<IInteract>(InteractedActor);
if (Interface)
{
UE_LOG(LogTemp, Warning, TEXT("Cast successful"))
}
}

这也是ACharacterBase的头文件。

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "CharacterBase.generated.h"
UCLASS()
class STRGZR_API ACharacterBase : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ACharacterBase();
protected:
UFUNCTION(BlueprintCallable, Category = "Interaction")
FHitResult LineTraceForward();
UFUNCTION(BlueprintCallable, Category = "Input")
void OnInteract();
public: 
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

我不知道为什么,但演员阵容在这里失败了:

AActor* InteractedActor = LineTraceForward().GetActor();
IInteract* Interface = Cast<IInteract>(InteractedActor);
if (Interface)
{
UE_LOG(LogTemp, Warning, TEXT("Cast successful"))
}

我的第二个问题是为什么这个转换不起作用,有没有更好的方法来调用Interact(ACharacterBase* Caller(AInteractable上?

感谢您的帮助!

关于virtualoverride

以下是动态多态性的基本用法:

class IInterface {
public:
virtual void method() = 0;
};
class CClass : public IInterface {
public:
void method() override { // do smth }
};
int main() { 
IInterface* ptr = new CClass();
ptr->method();
}

(不要忘记删除 ptr 或使用引用计数(

您可以在此处阅读有关虚拟方法的信息:

https://en.cppreference.com/w/cpp/language/virtual

https://en.cppreference.com/w/cpp/language/override

至于Cast<T>- 我不熟悉虚幻引擎,但它似乎是某种dynamic_cast<T>。如果没有类内部具有虚拟表,则无法执行多态转换,这是由virtual方法的定义提供的 (https://en.cppreference.com/w/cpp/language/object#Polymorphic_objects https://en.cppreference.com/w/cpp/language/dynamic_cast(。

  • 你应该把UFUNCTION(BlueprintCallable)说明符放在IInteract里面的函数声明上,而不是在实现的参与者上。

  • 实现参与者应使用以下声明进行重写:

    void Interact_Implementation(ACharacterBase* Caller) override;

  • 您不应该通过使用Cast来检查参与者是否实现接口,而是通过调用:

    actor->Implements<UInteract>()

  • 应使用以下方法调用接口方法:

    IInterface::Execute_Interact(someInteractable, caller)

因此,您永远不应该有理由投射到接口。

此外,您尚未验证您的线路跟踪是否确实击中了AInteractable演员。