I am trying to create multiple UStaticMeshComponent by using for loop but Unreal Engine keeps triggering breakpoint on CreateDefaultSubobject in Object.h(Not in my code, it's from UE4 core API). When I'm creating a single component it's working fine. I am pretty new to UnrealEngine and C++ so I might be doing something dumb but please be easy on that:)

Thank you so much for your help.

Header

#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); } 

Where it triggering breakpoint on the Object.h from UE4 API

 /** * 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 Answers

You used the same name for two different calls to CreateDefaultSubobject.

I ran your code in a new UE4 C++ project and got the following error message:

Fatal error: [File:D:\Build++UE4\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp] [Line: 3755] Default subobject StaticMeshComponent Sphere already exists for FlowSphere /Script/MyProject.Default__FlowSphere.

Also, the code you posted didn't compile.

item.AttachTo(this->RootComponent); 

should have been:

item->AttachTo(this->RootComponent); 

and you also needed to include "Components/StaticMeshComponent.h". Here is the corrected code:

#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; } 

So I had to do the same thing recently and ran into a lot of issues but the two major things to fix are:

  1. use UInstancedStaticMesh instead of UStaticMesh.
  2. add a property to your static mesh.

Below is the correct code.

#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; } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.