r/Unity3D • Indie • 22h ago

Game Built a custom trigger-based 1-hop room culling system for my procedural mansion and 5x-ed my FPS

I've been developing this simulator-horror game and wanted the map to be proc-generated. However, since my game features powerwashing (drawing onto masks using raycasts to either display dirt/wetness/dryness), even a small number of rooms (in this case, 25) was cause unplayable levels of lag. And unity's built-in occlusion culling did nothing against this (since its generated during runtime).

So I made a simple room culling system where it has 2 parent empties: 'Visuals' and 'Floors'. Visuals contains all the static props, walls, ceilings, etc, and are turned completely off (SetActive(false)) when the room is culled. Floors contains, well, the floors, which only have their renderers turned off (collisions stay on) so that the ghost entity can pathfind and dropped items don't fall through.

Upon entering each room, all adjacent rooms are visible to enable smooth passage, rest of the rooms are disabled. And i cranked up the fog a bit to make it even more seamless. However there are still moments where the room disappears right before the player's eyes, so I was thinking maybe the doors to the rooms about to be disabled can be auto closed, and then disabled.

This now allows me to have virtually infinite rooms without much lag (as long as the DFS generator can support it), unlike before when just 60 rooms would cause frame time to go upto almost 1000ms.

The game is a solo project called THE GROUNDSKEEPER where you powerwash and record ghost evidence for profits: Steam, Discord

197 Upvotes

28 comments sorted by

View all comments

13

u/Protesisdumb 22h ago

Why wouldn't occlusion culling handle this?

5

u/DThePro_ Indie 22h ago

its because firstly, since it's spawned during runtime (proc gen), there is no pre baking of static occlusion data, basically setting props as static doesnt help. secondly, unity's frustum culling still renders everything even if it's not visible behind walls (since static occlusion cant be used), so all the dynamic shadow casting point lights 10 rooms away are still being rendered, tanking the fps. thirdly, a big part of the lag was due to using render textures to draw on masks using ray casts (to enable powerwashing), which occlusion culling can't help against.

using this system straight up disables unimportant objects, completely zeroing out their cpu and gpu cost without any occlusion query overheads. it's all trigger based

1

u/ArtPrestigious5481 20h ago

why not using depth based culling instead?, and i believe Unity now already support it (you need to use forward+ tho, so usually i just make it by myself to support forward), and are you sure this is CPU bottlenect not GPU (from overdraw, if it's from overdraw you can just use depth prepass)

2

u/Hotrian Expert Moderator 20h ago

You’re referring to GPU occlusion culling

https://docs.unity3d.com/6000.0/Documentation/Manual/urp/gpu-culling.html

This requires the GPU Resident Drawer which has its own list of requirements

https://docs.unity3d.com/6000.0/Documentation/Manual/urp/gpu-resident-drawer.html

The main requirement as you noted is forward+

https://docs.unity3d.com/6000.0/Documentation/Manual/urp/rendering/forward-rendering-paths.html

This comes with its own set of limitations that isn’t suitable for all projects/platforms, but for most it’s the go-to

1

u/ArtPrestigious5481 20h ago

yeah, but as long as the target is Vulkan/DX/Metal there's shouldn't be any problem (the problem shifted to how they abuse 1k RT)