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

问题描述 投票:0回答:2

我一直试图在游戏中进行互动,但是我做错了事,我不知道在哪里!我将在下面包含一堆代码,并省略无关的位。

我在引擎中创建界面。结果类称为IInteract。它仅包含一个称为v​​oid Interact(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)。这是AInteractable的代码。

#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 *调用者)的定义。

#include "Interactable.h"

// Sets default values
AInteractable::AInteractable()
{

}

void AInteractable::Interact(ACharacterBase* Caller)
{
    Destroy();
}

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

现在,我设置了键绑定,以便在按下交互键时调用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"))
    }

我的第二个问题是,为什么这个强制转换不起作用,并且有更好的方法在AInteractable

上调用Interact(ACharacterBase * Caller))>>?

感谢您的帮助!

我一直试图在游戏中进行互动,但是我做错了事,我不知道在哪里!我将在下面包含一堆代码,并省略无关的位。我在...

关于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>-我对虚幻引擎不熟悉,但是appears是某种dynamic_cast<T>。如果没有在类中包含虚拟表的类,则无法执行多态转换,该类由virtual方法的定义(https://en.cppreference.com/w/cpp/language/object#Polymorphic_objectshttps://en.cppreference.com/w/cpp/language/dynamic_cast)。

  • 您应该将UFUNCTION(BlueprintCallable)说明符放在IInteract内的函数声明上,而不是在实现角色上。

  • 实施者应该使用此声明覆盖:

  • void Interact_Implementation(ACharacterBase* Caller) override;

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

    actor->Implements<UInteract>()

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

    IInterface::Execute_Interact(someInteractable, caller)

  • 此外,您还没有验证您的行迹是否确实击中了AInteractable演员。

    c++ unreal-engine4
    2个回答
    0
    投票

    关于virtualoverride


    0
    投票
    • 您应该将UFUNCTION(BlueprintCallable)说明符放在IInteract内的函数声明上,而不是在实现角色上。

    © www.soinside.com 2019 - 2024. All rights reserved.