Poor performance once I spawn 800 random static meshes

Hi, I am a newb, started learning a couple of weeks ago. I have a pawn class which in the constructor has:

collision = CreateDefaultSubobject(TEXT("collision")); SetRootComponent(collision);
body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("mainMesh"));
body->SetupAttachment(GetRootComponent());
ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMeshAsset(
	TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
body->SetStaticMesh(SphereMeshAsset.Object);

// add cube item
for (int i = 0; i < 800; ++i)
{
	FMath::RandInit(rand());
	FName name = FName(*FString::Printf(TEXT("item%d"), i));
	auto item = CreateDefaultSubobject<UStaticMeshComponent>(name);
	items.Add(item);
	// item->SetupAttachment(GetRootComponent());
	item->SetupAttachment(collision);
	
	ConstructorHelpers::FObjectFinder<UStaticMesh> meshAsset(
		TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));
	item->SetUsingAbsoluteRotation(false);
	item->SetStaticMesh(meshAsset.Object);
	// item->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	// item->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
	item->SetSimulatePhysics(false);
	item->SetEnableGravity(false);
	item->SetRelativeScale3D(FVector(
		FMath::FRandRange(0.01f, 1.f),
		FMath::FRandRange(0.01f, 1.f),
		FMath::FRandRange(0.01f, 1.f)
	));
	// // item->SetWorldScale3D(FVector(0.5f, 0.5f, 0.5f));
	// // item->SetRelativeLocation(FVector(0.f, 150.f, 0.f));
	// // item->SetRelativeRotation(FRotator(0.f, 0.f, 0.f));
	// // item->AddLocalOffset(FVector(0.f, 150.f, 0.f));
	// // change item pivot offset
	item->SetWorldLocation(FVector(
		FMath::FRandRange(-200.f, 200.f),
		FMath::FRandRange(-200.f, 200.f),
		FMath::FRandRange(-200.f, 200.f)
	));
	item->GetBodyInstance()->bOverrideMass = true;
	item->SetMassOverrideInKg(NAME_None, 100.f);
	item->BodyInstance.bLockRotation = false;
	item->BodyInstance.bLockXRotation = false;
	item->BodyInstance.bLockYRotation = false;
	item->BodyInstance.bLockZRotation = false;
	item->GetBodyInstance()->UpdateMassProperties();
	item->GetBodyInstance()->UpdateDampingProperties();
	item->GetBodyInstance()->UpdateInstanceSimulatePhysics();
}

And this drops the fps to 25fps. I am running this on a 7950x and a rtx 4090.

For visual reference it looks like:

I am not sure if it is because I am using these built in meshes or if they all have physics enabled, although activating the debug it seems the GPU time is the issue.

Also tried cooking/building a standalone and also low FPS.

Thanks.

The Actor / Component classes are quite heavy runtime objects.
Having an actor with 800 components isn’t a really great idea.
Try 1 Instanced Static Mesh component instead:

UHierarchicalInstancedStaticMeshComponent | Unreal Engine 5.2 Documentation


If you absolutely need it to be a StaticMesh asset, it’s also possible to use UDynamicMesh to generate the model then later export a StaticMesh asset.

4 Likes

To explain more-fully, the instance is a transform (a scaling, rotation, and translation). The mesh gets sent one time along with a list of transforms, so the overhead for X meshes is 1 mesh + a small list of scalar values, versus 800 distinct components with possible attachments, etc. Components can also have interfaces, class-defaults and whatnot applied to them further increasing possible overhead vs just-place-a-mesh-here with an instance.

1 Like

Thanks guys. I was aware of the instancing concept from way back when I tried 2d game dev (alteast I think so if instancing is the same in the sprite use case of just changing rotation and scale) but kind of created different meshes on purpose as I wanted to simulate a game I am ashamed to admit I used to enjoy, katamari on the PS2:

Basically you keep agglomerating different items you find along the way, probably ending up with hundreds of instances of I’d say about 50 different models.

It just seems like 800 should be a piece of cake even if each have 100 triangles it would be 80000 polygons.

In terms of the dynamic mesh idea I was kind of thinking of that, once you spawn a new mesh you’d merge it to the main mesh.

I am stubborn and still think there might be something else at play here, maybe physics or something.

Going off track a bit I’m used to Linux dev where I can profile stuff easily but with Unreal+Windows maybe because of my ignorance it is a nightmare to know what is going on in terms of crashes (having a detailed backtrace would be good) and profiling code and getting breakdown by function.

Anywho thanks again.

== edited
Seems it is the collisions, if I disable them fps shoots up

800 blueprints which are not just-static-meshes but as a class-item, might have a tick-operation enabled, other things that need be evaluated beyond just-a-mesh.

Plus as noted, it’s not just-a-mesh, but a component of a blueprint which needs to be evaluated, checked if any code runs, etc.

1 Like

Using Unreal Insights with the AssetLoadTime ticked, is actually quite nice for profiling, but you have to know about it :smiley:

1 Like

You are right, pardon my ignorance. As an example I then attempted using static mesh instances just to check and was able to render much much more without a problem

Thank you for the tip :slight_smile:

1 Like

Collisions will also get you here (performance).

A lot of games use a sphere around the player to check which things are in ‘interactivity-range’ so you can only enable stuff you need to when it’s appropriate, otherwise most costly-things would be disabled or ‘turned-off’ in terms of physics, etc. Think how souls/etc would need to check if something is in range to lock-on to the critter, but with other stuffs.

In your case, however, I’ve been mulling it around and unsure what you can do. I was thinking you could keep a library of simple collision-shapes and muck around with those, but unsure how performant it might be… You wouldn’t want collision on anything unless it’s just-about to be aggregated into the ball. Do collision-checks from the ball to anything within range-X.

Collision-wise, overall, I would think you will always start with a sphere and it’s more what is sticking OUT from the ball-of-things that makes it roll weird (I did play this game). Taking a sphere-collision and then welding a capsule to it but such that it sticks out so it rolls oddly? Then as you add more and more, you can recheck the configuration of your ball and adjust accordingly. Maybe each mesh has a simple collision-type (sphere, cylinder, cube, etc), and just attach ‘that’?

Things of a certain size that are smaller vs the current size of the ball would add little/no collision so as it gets bigger, you could get away with testing less-and-less?

Musing out loud, hope it helps.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.