ECS and LOD For Dynamic Entities

Hello everyone, we are developing our new game using ECS and Netcode for Entities. Aside from the usual challenges we are facing—which we overcome by spending quite a bit of time but with great satisfaction—we might be encountering an issue regarding the use of an LOD Group for our units. They are not static objects.

The LOD Group in the GameObject we bake from is correctly configured.
We have analyzed the entities, and they all have two LOD components directly converted from the Bake.

However, they are not working. I haven’t found much documentation explaining how to properly configure this, but it seems that LOD does not work for dynamic objects.
Has anyone managed to get it working? If so, could you share some tips?

It has been a while since I’ve used Unity’s LOD system as I have since wrote my own to support LOD crossfade. But if I recall correctly, the LOD system only works if the transform of the baked LOD Group entity moved, and it didn’t support dynamic scaling.

I figured as much from the behavior I observed. Could you give me some tips on how you made your system to apply LOD to entities?

If you just want an implementation to try, my solution is in the Kinemation module of my framework (link in sig). If it is still February, use the 0.12 branch as that’s in beta and has a bunch of bug fixes. LOD Group just works (except your crossfades can’t use animated mode). But for spammed rigid objects like props or projectiles, you may find the LOD Pack is even more performant, as that one packs up to 3 LOD levels into a single entity.

As for how I did this, 2 years prior to starting, I started heavily modifying Entities Graphics to solve other performance problems I was facing. When I took on LODs last year, I rewrote the LOD system to operate inside this modified version, which gave me access to the APIs I needed to make crossfades work. So the overall solution is not trivial and would be hard to replicate.

One of the things I did was reformulate the LOD equations so that runtime evaluation would evaluate in screen-space with dynamic scale rather than world-space distances. I also made the aggressive assumption that all child LODs of a LOD Group typically have the same transform (usually zero position) so I removed the LOD Group reference entity entirely and just made each LOD entity do everything for itself. And for LOD Pack, I packed LOD Masks and LOD selects into unused bits of RenderMeshArray and MaterialMeshInfo ranges which are used for submesh sharing. And then when generating the draw commands, I do a last-minute mask filter.

If none of that made sense, don’t feel bad. It is a lot of advanced concepts that are hard to summarize in a post like this. But feel free to ask more specific questions if you have them!

Unfortunately, I also need animations. I took a quick look at your work, and I think I’ll give it a more in-depth read over the next few days. It looks like a very deep and impressive piece of work. I’m not sure yet whether I’ll push forward with the LOD implementation or not. I need to release the game by the second quarter of next year.

I ran some load tests, and pure ECS handles around 7,000 entities without LOD. A hybrid solution, on the other hand, only reaches 2,000. I wanted to improve the performance of the pure ECS version, but it seems like the cost-benefit ratio isn’t great. Right now, the main bottleneck is the GPU with all those entities. I was hoping to offload it a bit.

For what it is worth, this was the main reason I modified Entities Graphics to begin with. I needed proper skinned mesh culling, and I ended up discovering property upload culling in the process which is a massive GPU optimization. And with LOD crossfade, LODs can be pushed a lot closer to the camera reducing triangle count, which tends to be a common GPU bottleneck in ECS projects.

All that is to say I am well-versed in the problems you are facing, so feel free to reach out here, in PMs, or through Discord.

You’re super kind! I’ll definitely ask you for some advice. It’s really difficult to share the challenges we face… and they come in so many different forms.