InstancedStaticMeshComponent slow in C++ but not in Blueprint

I am using an InstancedStaticMeshComponent to render many instances of a very simple mesh into my level. Given a length and a width as properties on the owning actor, I instance the mesh at even steps within a 2D area. Very simply, I for-loop over the X and Y, build a transform from it, add that transform to an array, and pass that array to the component using AddInstances.

I did this first in blueprint as proof-of-concept with great success, and it seemed to render the number of meshes I need without any performance issues. I did this in the construction script so that the instances will appear as I change the X and Y properties in editor.

I then ported this over to C++, placing the logic in the OnConstruction handle. This time, however, the performance is not nearly as smooth. Even a handful of instances causes the editor to slow down, and the construction causes noticeable hangups of around 1 second for only a handful of instances (100 in a 10x10 grid). On top of this, this c++ version causes the framerate of the editor to drop massively when the actor is selected, and even further when the component itself is selected. The act of selecting the actor itself results in repeated hangups.

As far as I can tell, the ‘algorithm’ I use between the blueprint POC and the c++ version are exactly the same, so I can only assume there is some quirk of how the component is constructed in c++ that I am not privy to.

Here is the Blueprint POC in question:


Construction script (bottom right) basically just calls this function which is the loop in question, and the resulting array is passed to an Add Instances node.

The respective c++:

AGridISM::AGridISM()
{

	ISMComponent = CreateDefaultSubobject<UInstancedStaticMeshComponent>("ISMComponent");
	auto debugMesh = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("/Grid/Meshes/Debug/DebugSenseVisualization"));
	auto debugMaterial = ConstructorHelpers::FObjectFinder<UMaterial>(TEXT("/Grid/Materials/Debug/TileVizualizeDecal"));
	SetRootComponent(ISMComponent);
	ISMComponent->SetStaticMesh(debugMesh.Object);
	ISMComponent->SetMaterial(0, debugMaterial.Object);
	
}

void AGridISM::OnConstruction(const FTransform& Transform)
{
	Super::OnConstruction(Transform);
	TArray<FTransform> Transforms;
	for (int x = 0; x < X; ++x)
	{
		for (int y = 0; y < Y; ++y)
		{
			auto halfTile = size / 2;
			auto baseLine = FVector2D(
				halfTile * -(X - 1),
				halfTile * -(Y - 1)
			);
			auto xy = baseLine + FVector2D(size, size) * FVector2D(x, y);
			Transforms.Add(
				FTransform(
					FRotator::ZeroRotator,
					FVector(xy.X, xy.Y, 0),
					FVector(1, 1, -height)
				)
			);
		}
	}
	ISMComponent->AddInstances(Transforms, false, false);
}

I would note that both of these approaches subclass AActor, so there’s no difference there. The DebugSenseVisualization static mesh and the TileVizualizeDecal material are also the same ones used by the blueprint. As far as I can tell, there is no difference at all. Does anybody have any clue why the latter runs so much worse?

I got the answer from a user on the Unreal Slackers discord server.
Thanks Danger Cloud#8063;

The issue had to do with the editor visbility level of the component property. I removed the VisibleAnywhere modifier and it resolved the issue. I don’t know if there’s a middle-ground that works, but for my case I don’t actually need to see this component in the editor so I’m happy with this.