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));
}
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:
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.