Download

C++ Spline Meshes causing low FPS and High Stat Unit Numbers Despite Culling.

Hi, for my spline based road system I am adding lots of small meshes, there are about 150’000 in total for the whole road system.

The mesh itself is quite simple with 264 triangles at LOD 0 going down to 32 triangles for the final LOD

I’m getting abot 20FPS in PIE and Stat Unit shows GPU 49ms when playing in the editor.

This I could understand given the number of spline meshes involved, as there would be a horrendous number of draw calls, if it weren’t for the fact that I have culling set at 10’000, so there are only a small number of meshes being drawn at any one time. None of the processor cores are getting maxed out and the GPU is running at about 20% in Task Manager

Is there anything fundamentaly wrong with the code I’m using within BeginPlay?



            USplineMeshComponent *splineMesh = NewObject<USplineMeshComponent>(this);

            splineMesh->RegisterComponent();
            splineMesh->CreationMethod = EComponentCreationMethod::UserConstructionScript;

            splineMesh->SetForwardAxis(ESplineMeshAxis::X);
            splineMesh->SetMobility(EComponentMobility::Type::Static);


            UStaticMesh* RoadMesh = LoadObject<UStaticMesh>(nullptr, TEXT("StaticMesh'/Game/Meshes/RoadMeshes/10m_straight.10m_straight'"));
            splineMesh->SetStaticMesh(RoadMesh);
            splineMesh->SetCullDistance(10000);
            UMaterialInterface* RoadMat = LoadObject<UMaterialInterface>(nullptr, TEXT("MaterialInstanceConstant'/Game/Meshes/RoadMeshes/curb_Inst.curb_Inst'"));
            UMaterialInterface* PavementMat = LoadObject<UMaterialInterface>(nullptr, TEXT("MaterialInstanceConstant'/Game/Meshes/RoadMeshes/pavement_Inst.pavement_Inst'"));
            UMaterialInterface* CurbMat = LoadObject<UMaterialInterface>(nullptr, TEXT("MaterialInstanceConstant'/Game/Meshes/RoadMeshes/Roadmaterial_Inst.Roadmaterial_Inst'"));
            splineMesh->SetMaterial(0, RoadMat);
            splineMesh->SetMaterial(1, PavementMat);
            splineMesh->SetMaterial(2, CurbMat);

            splineMesh->SetStartAndEnd(splinePointLocation, splinePointTangent, splinePointLocation2, splinePointTangent2);

            splineMesh->SetCollisionEnabled(ECollisionEnabled::QueryOnly);

            splineMesh->AttachToComponent(Splines[RoadNumber], FAttachmentTransformRules::FAttachmentTransformRules(EAttachmentRule::KeepRelative, true));
            A_SplineMesh.Add(splineMesh);




Stat GPU result from the console

Because I’m culling the meshes at such a short distance I would have expected a decent framerate in the 60fps range


This is the Frame,Game,Draw and CPU.

I managed to get GPU down to 42ms from 49ms, and fps to 24fps by setting collision to Simple. Materials are instances and the base materials are ticked for use with spline meshes.

Suspecting that the high GPU value was related to draw calls I ran a Stat Scenerendering from the console. If I am reading this right then I assume InitViews should be where I need to start digging?

150 thousand spline meshes? That’s way too much, seriously. That’s so many static objects even culling becomes a problem. You should try to think of solutions to reduce that number by at least 10x. Also, this plugin might help: https://www.unrealengine.com/marketplace/en-US/slug/fast-procedural-splinemesh

Thanks Manoel, if culling is an issue with this many meshes then I’ll just split them up and use level streaming. Splitting amongst 30 levels should get it down to 5000 meshes per level, so at any one time there should be no more than 15000 meshes, although in road denser parts of my levels that figure may jump dramatically. I assume the plugin in your link is merging the spline meshes, which is an interesting idea. HISMs is certain out of the question because I need the road mesh to be deformed to match the terrain.

Merging of the spline meshes on a per road basis would seem like a sensible approach to take, even if I do end up splitting the road network into 30 streaming level groups.

I don’t have any objections to third party plugin, but I would prefer not to be reliant on plugins, as anything supported by a single developer leaves my game vulnerable to a single developer that may not decide to upgrade their plugin when there is an engine update.

Not sure what was going off but ultimately the issue went away after I upgraded the engine version from 4.21 to 4.22. Now I see about 70fps and about 11ms.