在 UnrealEngine 中动态创建一个 SphereComponent

Dynamically create a SphereComponent in UnrealEngine

我试图在关卡开始后 2 秒动态创建一个 SphereComponent。为此,我有以下代码:

void ACollidingPawnSpawnPawns::DelayedFunction() {
         // The first parameter 'SphereComponent' is the main component in the level and it has been created using the CreateDefaultSubobject method in the constructor of this class.  But that method can't be used outside the constructor.
         USphereComponent *dynamicallyCreatedSphere = NewObject<USphereComponent>(SphereComponent, USphereComponent::StaticClass());
             dynamicallyCreatedSphere ->InitSphereRadius(30.0f);
             dynamicallyCreatedSphere ->SetCollisionProfileName(TEXT("Pawn"));
             dynamicallyCreatedSphere ->SetRelativeLocation(FVector(155.0f, 165.0f, 45.0f));
             dynamicallyCreatedSphere ->SetVisibility(true);
 }

在我 运行 关卡后,我没有看到这个动态球体弹出。

对于显示的主要 'SphereComponent',此代码位于构造函数中:

// Our root component will be a sphere that reacts to physics
 SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
 RootComponent = SphereComponent;
 SphereComponent->InitSphereRadius(40.0f);
 SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
 
    // Create and position a mesh component so we can see where our sphere is
     UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
     SphereVisual->SetupAttachment(RootComponent);
     static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
     if (SphereVisualAsset.Succeeded())
     {
         SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
         SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
         SphereVisual->SetWorldScale3D(FVector(0.8f));
     }

但是我还是不能使用 CreateDefaultSubobject 在构造函数外创建 UStaticMeshComponent。

所以我想象要在我的关卡中看到我的 dynamicallyCreatedSphere 我将不得不创建一个 UStaticMeshComponent 并且我将需要 FObjectFinder 方法的一些变体来调用(这个 FObjectFinder 在构造函数之外也不起作用)。

我已经坚持了一段时间了。有人知道怎么做吗?

2021-12-2更新 感谢下面 的建议,这是我必须动态创建球体的最终代码:

在cpp文件中:

void ACollidingPawnSpawnPawns::spawnPawns()
{
    if (dynamicallyCreatedSphere == nullptr) {
        //dynamicallyCreatedSphere = NewObject<USphereComponent>(USphereComponent::StaticClass()); // compiles
        dynamicallyCreatedSphere = NewObject<USphereComponent>(SphereComponent, USphereComponent::StaticClass());
        //dynamicallyCreatedSphere->SetupAttachment(SphereComponent);
        dynamicallyCreatedSphere->InitSphereRadius(30.0f);
        dynamicallyCreatedSphere->SetCollisionProfileName(TEXT("Pawn"));
        dynamicallyCreatedSphere->SetRelativeLocation(FVector(155.0f, 165.0f, 45.0f));
        dynamicallyCreatedSphere->SetVisibility(true);


        dynamicMesh = NewObject<UStaticMeshComponent>(this);
        dynamicMesh->AttachToComponent(dynamicallyCreatedSphere, FAttachmentTransformRules::KeepWorldTransform);
        dynamicMesh->RegisterComponent();
        dynamicMesh->SetStaticMesh(StaticMesh);
    }
}

在 .h 文件中我有这 3 行:

UPROPERTY(EditAnywhere)
UStaticMesh* StaticMesh;

USphereComponent* dynamicallyCreatedSphere = nullptr;
UStaticMeshComponent* dynamicMesh = nullptr;

将 StaticMesh 声明为 UProperty 允许我在 UE 界面中手动 select 网格。然后当我运行关卡的时候把StaticMesh插入到dynamicMesh变量中。

首先,只有NewObject可以用于在构造函数之外创建组件:

void ACollidingPawnSpawnPawns::DelayedFunction() 
{
    // you should specify outer as current actor (because this component is part of it)
    USphereComponent* DynamicallyCreatedSphere = NewObject<USphereComponent>(this, USphereComponent::StaticClass());
    DynamicallyCreatedSphere->RegisterComponent();
    // when component is dynamically created, you can use AttachToComponent, not SetupAttachment
    DynamicallyCreatedSphere->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
    DynamicallyCreatedSphere->InitSphereRadius(30.0f);
    DynamicallyCreatedSphere->SetCollisionProfileName(TEXT("Pawn"));
    DynamicallyCreatedSphere->SetRelativeLocation(FVector(155.0f, 165.0f, 45.0f));
    DynamicallyCreatedSphere->SetVisibility(true);
}

而不是 FObjectFinder 你可以使用 LoadObject 来加载指定路径的东西。但我认为这是不合时宜的方式,因为 ref 是硬编码的。 在 UCLASS 中使用以下代码:

UPROPERTY(EditAnywhere) 
UStaticMesh* StaticMesh;

并直接指定静态网格:SphereVisual->SetStaticMesh(StaticMesh);

之后您可以继承 C++ class 来制作蓝图并从 Content Browser 中选择 StaticMesh。