虚幻引擎:如何在循环中创建UStaticMeshComponent?

时间:2019-03-13 17:50:00

标签: c++ unreal-engine4

我正在尝试使用for循环创建多个UStaticMeshComponent,但虚幻引擎会继续在CreateDefaultSubobject中的Object.h上触发断点(不是我的代码,它来自UE4核心API)。当我创建单个组件时,它工作正常。我对UnrealEngine和C ++还是很陌生,所以我可能在做一些愚蠢的事情,但是请保持简单:)

非常感谢您的帮助。

标题

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FlowSphere.generated.h"

UCLASS()
class CPP_PRACTICE_3_API AFlowSphere : public AActor
{
    GENERATED_BODY()

public: 
    // Sets default values for this actor's properties
    AFlowSphere();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

private:
    //UPROPERTY()
    //TArray<UStaticMeshComponent*> StaticMeshComponents;

    UStaticMeshComponent* test;

};

C ++

#include "FlowSphere.h"

// Sets default values
AFlowSphere::AFlowSphere()
{
    int32 amount = 100;

    RootComponent = CreateDefaultSubobject<USceneComponent>("SceneComponent");

    for (int32 i = 0; i < amount; i++) {

        //WHEN I INCLUDE THE LINE BELOW, UE4 START MAKING BREAKPOINT
        UStaticMeshComponent* item = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Sphere"));
        item.AttachTo(this->RootComponent);

    }

    //THIS WORKS FINE
    this->test = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("HELLO")); 
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AFlowSphere::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AFlowSphere::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

它在UE4 API的Object.h上触发断点的地方

    /**
    * Create a component or subobject
    * @param    TReturnType                 class of return type, all overrides must be of this type
    * @param    SubobjectName               name of the new component
    * @param    bTransient                  true if the component is being assigned to a transient property. This does not make the component itself transient, but does stop it from inheriting parent defaults
    */
    template<class TReturnType>
    TReturnType* CreateDefaultSubobject(FName SubobjectName, bool bTransient = false)
    {
        UClass* ReturnType = TReturnType::StaticClass();
        return static_cast<TReturnType*>(CreateDefaultSubobject(SubobjectName, ReturnType, ReturnType, /*bIsRequired =*/ true, /*bIsAbstract =*/ false, bTransient));
    }

2 个答案:

答案 0 :(得分:1)

所以我最近不得不做同样的事情并遇到了很多问题,但要解决的两个主要问题是:

  1. 使用 UInstancedStaticMesh 而不是 UStaticMesh。
  2. 向静态网格物体添加属性。

以下是正确的代码。

#include "FlowSphere.h"
#include "Components/StaticMeshComponent.h"
#include "UObject/ConstructorHelpers.h"

// Sets default values
AFlowSphere::AFlowSphere()
{
    int32 amount = 100;

    RootComponent = CreateDefaultSubobject<USceneComponent>("SceneComponent");

    for (int32 i = 0; i < amount; i++) {

        FName name = *FString::Printf(TEXT("Sphere %i"), i);
        FName c_name = *FString::Printf(TEXT("ChildSceneComponent %i"), i);

        UPROPERTY(EditAnywhere)
            USceneComponent* ChildSceneComponent
            = CreateDefaultSubobject<USceneComponent>(c_name);

        // instead of the regular static mesh, create and instance static mesh object with name assigned
        UInstancedStaticMeshComponent* item = CreateDefaultSubobject<UStaticMeshComponent>(name);
        item->RegisterComponent();

        // assign property to mesh if not you'll get a static mesh null property error like i did 
        auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));

        if (MeshAsset.Object != nullptr)
        {
            item->SetStaticMesh(MeshAsset.Object);
        }
        item->SetFlags(RF_Transactional);

        // add instance to actor level
        this->AddInstanceComponent(item);

        // make the scene component for the mesh to be visible
        RootComponent = Root;

        // attach mesh to the scene component of the actor in form of a Hierarchy

        item->AttachToComponent(ChildSceneComponent, FAttachmentTransformRules::KeepWorldTransform, m_name);
        ChildSceneComponent->AttachToComponent(Root, FAttachmentTransformRules::KeepWorldTransform, c_name);

        // set mesh transform based on the ith position
        FTransform t(FVector(250 * i, i, i));

        // activate the new copy of the mesh
        Mesh->AddInstance(t);

        // Offset and scale the child scene from the root scene as a precaution
        ChildSceneComponent->SetRelativeTransform(
            FTransform(FRotator(0, 0, 0),
                FVector(250 * i, i, i),
                FVector(0.1f))
        );


    }


    PrimaryActorTick.bCanEverTick = true;

}



    

答案 1 :(得分:0)

您对CreateDefaultSubobject的两次不同调用使用了相同的名称。

我在新的UE4 C ++项目中运行了您的代码,并收到以下错误消息:

  

致命错误:   [文件:D:\ Build ++ UE4 \ Sync \ Engine \ Source \ Runtime \ CoreUObject \ Private \ UObject \ UObjectGlobals.cpp]   [Line:3755]已经有默认的子对象StaticMeshComponent Sphere   FlowSphere /Script/MyProject.Default__FlowSphere存在。

此外,您发布的代码未编译。

item.AttachTo(this->RootComponent);

应该是:

item->AttachTo(this->RootComponent);

,并且您还需要包含“ Components / StaticMeshComponent.h”。这是更正的代码:

#include "FlowSphere.h"
#include "Components/StaticMeshComponent.h"

// Sets default values
AFlowSphere::AFlowSphere()
{
    int32 amount = 100;

    RootComponent = CreateDefaultSubobject<USceneComponent>("SceneComponent");

    for (int32 i = 0; i < amount; i++) {

        FName name = *FString::Printf(TEXT("Sphere %i"), i);
        UStaticMeshComponent* item = CreateDefaultSubobject<UStaticMeshComponent>(name);
        item->AttachTo(this->RootComponent);

    }

    this->test = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("HELLO"));
    PrimaryActorTick.bCanEverTick = true;

}