Posted April 23, 2023 by SourLemonStudio
Author: Mike McGoveran
4/22/03
The Problem:
Our current solution for dungeon Generation started to show signs of rapid performance degradation when testing larger empty dungeons. This prompted out first round of optimizations and testing, which required learning about Unreal Engine's performance monitor tools. Once we sorted out how to use these tools we found our game ticks being too expensive and our draw calls too high.
Considering this issue would drop the frames below 20 on a Developers machine, we would be looking at a complete failure for the end user on the average end user PC. This issue would be exaggerated further once we have finished populating the dungeon.
The Solution:
First we had to find what object were causing the frame loss. We had a hunch it was the torches as we were using Instanced static meshes for or walls, floors and ceilings which SHOULD be optimizing the draw calls. We had 2000+ torches in the level each with a point light and a particle system. The torches started in a state where the particle system was set to invisible until the player got close. We assumed that this would stop the particle system from ticking. We were wrong. By replacing the Torch mesh piece by piece we found the particle system was the primary issue. It turns out unreal still performs the particle math operations even when invisible and instead needs to be set to inactive. This instantly improved frames by about 30 frames on average. but this still wasn't enough performance.
Next we had to sort out frustum culling as 2000+ torch meshes are a draw call issue. So Micah found a cull volume option which was helping only with rooms but didn't seem to work for torches or hallways. So we found some settings on the actor itself that implemented culling and this resolved the issues with torches getting framerate back to 60-65 on a dungeon well beyond the realistic size.
The last step was to fix culling for the halls. Here we found that an instanced static mesh has to cull all it's children meshes at the same time in a bounding box equal to the largest piece. Since the player was always inside this bounding box it would never cull the halls unlike how it culls the rooms. The solution was changing the halls/Floors/Ceiling on the hall generation away from an instanced static mesh to stand alone static meshes. Now we have fully culled assets in the dungeon generation keeping framerate at expected numbers.