0

我试图在关卡启动后 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。

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

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

更新 2021-12-2 感谢以下https://stackoverflow.com/a/70180682/4722577的建议,这是我必须动态创建球体的最终代码:

在 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 界面中手动选择网格。然后当我运行关卡时,StaticMesh 被插入到 dynamicMesh 变量中。

4

1 回答 1

1

首先,只能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++ 类来蓝图并从 Content Browser 中选择 StaticMesh。

于 2021-12-01T07:52:39.213 回答