Static mesh foliage collision causing long load times

Hey there

Im having a serious problem with load times on my map that is super heavy in static mesh foliage instances.

From all my testing I think I have found that It is being caused by the creation of the collision bodies for every instance, that I believe occurs when the map is loaded.

My map is covered in tens of millions of foliage instances generated by procedural foliage volumes. All of my foliage needs to be interacted with via different trace functions, so collision for my foliage has to be enabled. Collision for foliage is set to “query only” with overlaps disabled and all channels ignored.

When playing in the editor and in packaged builds with foliage collision enabled the load time of the map takes hours. Once the loading is complete everything runs fine due to optimization and culling of the foliage etc, but the load times are unacceptable.

However when collision is disabled, loading only takes seconds, for both playing in the editor and packaged builds. This is the same if I replace the procedurally generated foliage with landscape grass types. I believe it is because they also have no collision and are only created near the player on demand and not across the entire map.

I have tried loading the map with all foliage collision disabled and enabling it when its needed, but even enabling collision on a small fraction of foliage at runtime creates unbearable lag and stutters on the game thread.

I was under the impression that regardless of whether collision is enabled or not, the collision hulls/bodies would be loaded along with the static mesh instance they belong too and that enabling collision should be instant or near to it, but after doing a trace I don’t think that’s the case. In the trace I have found an event “createAllInstanceBodies” to be causing the stutters and long lag periods and I suspect this is the confirmation that when collision is enabled on foliageInstanceStaticMeshComponents, the collision hulls/bodies are generated, at least for the first time such as on map load anyway.

I can’t just load and unload foliage actors with world partition either. I need my foliage actors to always be loaded as I need my large trees to always be visible. I can’t HLOD the trees either as all foliage has to be able to be chopped down or removed at runtime.

I guess I’m wondering if anyone knows of a way to solve this long load time problem created by loading a map with lots of instances that have collision enabled? I would like to force it to happen asynchronously after the map has loaded to avoid the noticeable stutter and lag, or to be able to enable collision on only a small number of instances at a time when they’re near the player, but without collision hulls its hard to find a performant solution for that.

An interesting note is that procedural foliage generation is also much faster when my foliage instance collision is disabled, regardless of whether “collision with world” is enabled in the foliage type.

Also I have tested this in UE 4.27, UE 5.3, and UE 5.4 and I get the same results with all three engine versions.

EDIT: Attached is a screenshot of the trace

Thanks in advance to anyone that takes the time to read all that or reply.

1 Like

What is bp tree manager?
Does deleting it solve the loading issue?

Tree manager is a BP I add to my world to control functions to do with interactions with my trees. Deleting it doesn’t help, I just recently added it to the map I was testing on so I could run an event at begin play to change the collision of some of the foliage components after the map had already loaded, but the foliage performance problem happens even on a completely clean new map. Recreated the problem in 4.27 and 5.4 as well with clean maps without tree manager or anything else.

The interesting thing is that at begin play and/or when the collision is enabled the first event is called “OnCreatePhysicsState” before the “CreateAllInstanceBodies” even though physics is disabled. Maybe its just a naming convention but seems strange it’s referencing physics even though its not enabled.

Also these two events don’t seem to take up an unreasonable amount of time themselves but they are followed immediately by a lengthy foreground task

No given this, i think its far more likely at least one of the models has bad/invalid collision hulls or other similar issues.

Try to leave the collision on, but effectively delete all the colisions off the meshes in a test only environment.

If loading is reduced to 0, try adding a simple spheal as collision to each mesh and see if the timing goes nuts or not.

This is also assuming that you don’t just find a mesh with 100+ hulls in there or some other similar issue.

Usually, if you want to you can set up the hull generation to a reasonable vertex/hull count and generate convex hulls for the objects within engine.
Would not reccomend doing this until you test out removing all of them first…

Also, performance wise - should it come to it -
One single sphere would be the least expensive option you can use to run a replacement algorhytm from your tree manager or any other external factor ny using collision checks.

Thanks for the tip

99% of my foliage static meshes all have a simple sphere for their collision and complex collision uses simple as complex. My tree complex collision pretty intense though so I’ll try turning that off for now and see what kind of effect that has. My test levels though were only using a single foliage type with a simple sphere collision and the load difference between collision on or off was still very noticeable.

As for your replacement algorithm idea, is it possible to replace or generate a collision hull for a mesh at runtime? that could come in handy.

Cheers

EDIT: After completely removing all collision hulls from my foliage static meshes. Loading was definitely faster but in the trace these two events still run regardless of if there’s collision hulls or not. The long foreground task is gone however. With the collision hulls gone and collision disabled however they went away and the load is almost instant.

The fun part though, is If I have collision disabled on my foliage on map load, and the foliage static mesh has no collision hulls/bodies and then I enable collision on my foliage instance components at runtime, I still get the massive lag/stutter I have been getting. So enabling collision on static meshes with no collision bodies still creates this lag.

1 Like

Can I get this working with my procedural foliage volumes? or do I have to use PCG?

Also I don’t just need to generate a proxy collision for bumping into, I need to be able to access the foliageinstancestaticmeshcomponents to send them custom data inputs. to change their material opacity and add movement when running through. Is this possible with this tool? Like swapping the instance with no collision to one that has collision?

Thanks

Yes this works with Foliage Actors/Volumes as well. You can swap the instance to a different Instance, Actor or DataLayer - so you can have completely different staticmeshes in the Actor or Instances all with their own collision.

That’s great, thanks.

I’ll have a play around.

Cheers

1 Like

You wouldn’t be able to give a very quick step by step of what I need to do to get that working would you?

I have a map covered in “static mesh foliage” from a mixture of procedural foliage volumes and painted foliage.

The foliage has collision disabled but I would like to swap them for versions where the collision is enabled once they’re in close proximity.

To interact with my foliage I use box and sphere traces to HIT individual instances and send them custom data values to affect their materials.

It doesn’t have to be super detailed, just a quick step by step would be helpful if at all possible. The tools are quite expansive and there’s a lot to wrap my mind around even with all the documentation on the website.

Cheers

Sure, I just need to finish a few things then I can help.

I’ve got a discord channel - if you want to go there it will be a bit easier to discuss:

1 Like

Have a try on 4.24 with hulls - even .25.
Just a hunch here that they fu*ked the .27 release when they shouldn’t have.
Just make sure whatever you try is using PhysX and not Chaos.

This probably boils down to;
Chaos is sh*t and Epic is clueless.

But you know, its nice to confirm it before making blanket statements.

Now, supposing this is true, to get your old project loading right after you confirm chaos is the issue, all you have to do is build from source using PhysX.
Easier said than done for 5…

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