Hey folks,
I have been an avid Blueprint user up to now, but as we all know C++ is the real deal. So I’ve been trying to get some routine with it and it’s working quite well. But now I have encountered my first real problem.
I wanted to give procedural world generation a shot and took my inspiration from the UE4 Training Stream. So far so good. I managed to recreate the basic functionality (at about the 8 minute mark in the video) in C++, and it works fine. Everything’s getting created just as expected. But there is one flaw: Once I have say 100x100 instanced meshes, it starts lagging (e.g. framrate goes down) in the editor. Now I know this did not happen when I created the procedural generation the blueprint way, so I suppose there’s a flaw in my code.
void AFFBox::OnConstruction (const FTransform& Transform)
{
CreateSimpleBoxGrid ();
}
void AFFBox::CreateSimpleBoxGrid ()
{
// Clear existing instances (just to be sure).
InstancedStaticMesh->ClearInstances ();
// Get maximum amount of boxes.
int GridSize = GridWidth * GridHeight;
// Get mesh size data.
FVector MeshExtent;
if (InstancedStaticMesh->StaticMesh != NULL)
{
MeshExtent = InstancedStaticMesh->StaticMesh->GetBounds ().BoxExtent;
}
else
{
return;
}
// Since we are only using cubes, it does not matter which axis we are using.
// Extent goes from center to one of the edges.
float BoxSize = MeshExtent.X * 2.0f;
// Create the instances.
for (int iElement = 0; iElement < GridSize; ++iElement)
{
int PositionY = (iElement / GridHeight) * BoxSize;
int PositionZ = (iElement % GridHeight) * BoxSize;
FTransform InstanceTransform = FTransform(FVector(0.0f, PositionY, -PositionZ));
// Move the instanced static mesh to the left depending on the grid width.
// Centers the pivot horizontally along all instances of the mesh.
if (bCenterPivotHorizontally)
{
InstanceTransform.AddToTranslation (FVector (0.0f, -(GridWidth / 2.0f * BoxSize) + BoxSize / 2.0f, 0.0f));
}
InstancedStaticMesh->AddInstance (InstanceTransform);
}
}
This is basically it, nothing too fancy. One thing I would like to point out is that if I remove the line “InstancedStaticMesh->ClearInstances ();”, it starts lagging even with a very low amount of instanced meshes. My guess would be that it constantly creates new meshes, even though it should just update when a change occurs, since we’re in the construction script.
Almost forgot, the CenterPivotHorizontally thingy is just for usability’s sake, it does not matter whether it is commented out or not.
results in an ever increasing number of mesh instances in the instanced mesh while I am in the editor! If I remember correctly using this setup with Blueprint only does not require me to clear the instanced static mesh beforehand. So what’s going on here?
Another quick update: Recreated the logic in blueprint only, everything is working fine. No need to clear the instanced mesh, no lag with 100x100 instances. Weird. Can anybody reproduce this issue in C++?
This is just a quick, untested at-a-glance idea, so take it with a grain of salt:
The Blueprint Construction Script acts as a sort of CDO construtor for actors. It is therefore only called once for the CDO for that blueprint.
On the other hand, I do believe OnConstruction is called on all instances of an actor. And by default, every single operation done on an actor in the editor ends up reconstructing it. So it will end up accumulating more and more copies of the exact same static mesh instances.
Try moving this initialization somewhere else – I’m thinking PostInitProperties, but that might be too early for the InstancedStaticMeshComponent to be ready.
Another thing I just remembered: before using the OnConstruction() call I had the “CreateSimpleBoxGrid()” function exposed to blueprints and called it right from the constructor in a blueprint I created - same faulty, laggy behavior.
Yet another update: I found the culprit! As it seems the problem lies with the UInstancedStaticMeshComponent. First of all, take a look at this:
Now what I did was to recreate the whole spawning process in a Blueprint derived from my custom class. In there I tried two things: a) Add the instances to the UInstancedStaticMeshComponent (“Instanced Static Mesh”) and b) add them to the “Newmesh”. The difference between the two is that the first was created in c++ and the latter in blueprint (e.g. simply add the component to the blueprint actor in the editor). And as expected, the first causes laggy behavior whereas the latter runs smoothly.
Just for the sake of completeness I also tried using something else as root - to no avail. So why is the UInstancedStaticMeshComponent behaving so wildly different from the one you can add as a component to blueprints?