簡體   English   中英

為什么我在 Unreal Engine 中遇到多態性和接口問題

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

我一直試圖在我的游戲中進行互動,但我做錯了,我不知道在哪里。 我將在下面包含一堆代碼並省略不相關的位。

我在引擎中創建界面。 生成的 class 稱為IInteract 它只包含一個 function 稱為void Interact(ACharacterBase* Caller) ACharacterBase只是我項目的默認 pawn。 這是 IInteract 的header文件。

#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 的 class並將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* Caller)的定義。

#include "Interactable.h"

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

}

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

我想我的第一個問題是,我應該在AInteractableIInteract的交互 function 上的什么地方使用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 的header文件。

#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> - 我不熟悉虛幻引擎,但它似乎是某種dynamic_cast<T> 如果 class 內部沒有虛擬表,則無法執行多態轉換,這是由virtual方法的定義提供的( https://en.cppreference.com/w/cpp/language/object#Polymorphic_objects https://en.cppreference.com/ w/cpp/language/dynamic_cast )。

  • 您應該將UFUNCTION(BlueprintCallable)說明符放在 IInteract 內的IInteract聲明上,而不是放在執行角色上。

  • 執行者應該使用這個聲明來覆蓋:

    void Interact_Implementation(ACharacterBase* Caller) override;

  • 您不應該使用Cast檢查 actor 是否實現了接口,而是通過調用:

    actor->Implements<UInteract>()

  • 您應該使用以下方法調用接口方法:

    IInterface::Execute_Interact(someInteractable, caller)

所以你永遠不應該有理由轉換到一個接口。

此外,您還沒有驗證您的線條跟蹤是否確實擊中了AInteractable actor。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM