我怎样才能在代码中创建一个抽象 class,让蓝图扩展它,然后将该蓝图返回给代码进行实例化?

How can I create an abstract class in code, let a blueprint extend it, and give that blueprint back to code to instantiate?

假设我想在代码中创建一个 AI class 用于控制 pawn,但我希望我的设计师能够使用蓝图修改行为以进行快速迭代。

假设我在 MyProjectBaseAI.h 中有这个:

#pragma once

#include "EngineMinimal.h"
#include "GameFramework/Actor.h"
#include "MyProjectBaseAI.generated.h"

UCLASS()
class MYPROJECT_API AMyProjectBaseAI : AActor
{
    GENERATED_BODY()
    
public:
    AMyProjectBaseAI(const FObjectInitializer& ObjectInitializer);

    virtual void BeginPlay() override;

    virtual void Tick(float DeltaSeconds) override;

    void SetGoalPosition(FVector pos);
  
    virtual void DetermineGoalPosition(int32 stateData1, int32 stateData2) = 0;

private:
    FVector goalPosition;
};

我想把这个 class 抽象化,并有一个蓝图能够实现 DetermineGoalPosition(...); 调用 SetGoalPosition(FVector pos) 取决于他们的 AI 设计。

那么,设计者如何在inspector中设置实现class,让我的C++代码实例化呢?假设我有一个 class 想要像这样实例化实现 class (当前使用基础 class):

AMyProjectBaseAI* ai = World->SpawnActor<AMyProjectBaseAI>(...);

摘要class设置:

  1. 使用 UCLASS 中的 AbstractBlueprintable 说明符将 class 标记为抽象的和可设计的(尽管当您继承自AActor 或另一个蓝图 class,Blueprintable 说明符是多余的)。

  2. DetermineGoalPositionUFUNCTION 说明符中使用 BlueprintImplementableEvent。这允许蓝图实现功能。

此外,不要将函数声明为虚拟函数,因为 ver 4.8:

根据 Unreal 的标准

New: Removed "virtual" keyword from several engine-level BlueprintImplementableEvents to conform to the new "BlueprintImplementableEvents should not be virtual" standard.

  1. SetGoalPositionUFUNCTION 说明符中使用 BlueprintCallable 属性。这允许从蓝图调用函数。

     #pragma once
    
     #include "EngineMinimal.h"
     #include "GameFramework/Actor.h"
     #include "MyProjectBaseAI.generated.h"
    
     UCLASS(Abstract, Blueprintable)
     class MYPROJECT_API AMyProjectBaseAI : AActor 
     {
         GENERATED_BODY()
    
     public:
         AMyProjectBaseAI(const FObjectInitializer& ObjectInitializer);
    
         virtual void BeginPlay() override;
    
         virtual void Tick(float DeltaSeconds) override;
    
         UFUNCTION(BlueprintCallable)
         void SetGoalPosition(FVector pos);
    
         UFUNCTION(BlueprintImplementableEvent)
         void DetermineGoalPosition(int32 stateData1, int32 stateData2);
    
     private:
         FVector goalPosition;
     };
    

实例化器设置

  1. 然后在 class 的 header 中你想在检查器中设置实现 class,有一个 public [=带有 EditAnywhere 说明符的 24=] 变量(或 EditDefaultsOnlyEditInstanceOnly 如果 subclass 应仅在编辑器中的蓝图或实例级别设置):

     public:
         UPROPERTY(EditAnywhere)
         TSubclassOf<AMyProjectBaseAI> AIImplementationClass;
    
  2. 然后在实例化它的地方,只需使用 AIImplementationClass 作为 class:

     AMyProjectBaseAI* ai = World->SpawnActor<AMyProjectBaseAI>(AIImplementationClass);