Level Streaming / Precomputed visibility troubles

In my game I have a big apartment building and you can randomly find keys to apartments and scavenge them. This is a lot of props though, and I haven’t even added everything I want yet. So, it takes a while to load and I get really low FPS. When I turn on wireframe the whole level is visible no matter where I go. My walls are brushes and I have tried switching them to static prop models but nothing seems to block visibility. I tried messing with Precomputed visibility but couldn’t figure out how to get it to work. I didn’t notice any FPS improvement from adding precomputed visibility volumes to the playable area and turning it on the world settings. (I tried messing around with it on a separate level but couldn’t figure it out.)

So, right now I have level streaming. Each apartment is its own level except player apartment which is part of the persistent level. But I am having little trouble with level streaming system.

I would like to:

  • Have all the apartment levels NOT be loaded when the game starts
  • Have the apartment level load when the front door is unlocked the first time
  • Have the apartment visibility turn on and off from a trigger or the level streaming volume (but only after the apartment is unlocked the first time)
  • Have all the items in the apartment continue to have collision even when they go invisible
  • Have items that are removed from the apartment not go invisible outside it

In the set up in this video I am using the “Always Loaded” streaming method. Meaning the levels are loaded from the beginning and the initial load time is a bit longer. Every apartment door has their own Level Streaming Volume with the “Loading And Visibility” setting. It works fine as for visibility. My FPS is back to normal and everything inside the apartment, including static props, goes invisible when I move away from the level streaming volume. But the problem, like shown in the video, is that everything also stops colliding.

I tried other settings too. If I didn’t set it to “Always Loaded” the level would reset itself if I would walk away from the level streaming volume and then back. Doors would close themselves, closets that spawn items when they are first opened would reset themselves and then respawn the items when I would revisit the apartment (ending up in double items).

The Level Streaming Usage settings are really confusing. Here’s how I understand the names:

  • SVB Loading (This would only load the level, but not turn on visibility)
  • SVB Loading and Visibility (This will load the level and set visiblity)
  • SVB Visiblity Blocking On Load (No idea what this means, though I assumed it would mean it only sets visibility)
  • SVB Blocking On Load (No idea what this means)
  • SVN Loading Not Visible (No idea how this would be different from SVB Loading)

In a lot of places “Blocking On Load” is just explained with “well, it means if you want to block it on load”.

I tried having the level “Initially Loaded” and then use either “Visibility Blocking On Load” or “Blocking On Load” but the streaming volume seems to override the “Initially Loaded” flag and will unload and load it when I step into the volume. I have no idea how to control just the visibility right now with streaming volumes. Also, if you have the Streaming Method as “Blueprint” then there’s two options “Initially Visible” and “Should be Visible” in the “Level Details” and I am not sure how they would be different.

In my current set up I have removed the Level Streaming Volumes and replaced them with Collision Boxes on the apartment door blueprint. The levels are not initially loaded, rather they are loaded with the “LoadStreamLevel” function when the apartment is unlocked the first time. Then I use the collision box on the apartment door to hide everything inside when the player steps away from it. I haven’t been able to get this work perfectly yet (something about the collision channels I must be doing wrong since it wont register the closets inside the apartment) but my fear is that it wont work perfectly. If something like the window prop was to be touching the collision box wouldn’t it still register as overlapping and hide when the player steps away? Also, since I am using the SetActorHiddenInGame input, it might create some problems. Some of my items might already want to be invisible (if they are for example inside another item). Using SetActorHiddenInGame would make them visible when not wanted when the player would step back inside the trigger.

I would like to use level streaming volumes rather than the collision boxes since it seems rather messy. It would help if I would be able to detect what level each item was originally from so that I could make sure nothing from outside the apartment can never be accidentally set hidden by the blueprint.

Hey Au-heppa,

There’s a lot of info here. I’ll just respond as I go through.

Wireframe mode does not cull the actors from being visible.

Precomputed Visibility Volumes are an offline form of visibility/occlusion culling. These have to be baked before hand so that the cells know whether an actor is visibile or not. If you’re targeting mobile these come in really handy since it does not have a form of dynamic occlusion culling and everything is rendered all the time.

To enable Precomputed Visibility Volumes you first need to go to the World Settings and enable it there. Then when you build the lighting for the level the cells will be placed on top of surfaces. The information on my site here can help you set these up until we get some official documentation for this: Precomputed Visibility Volumes

Also, keep in mind that these do not work well with streaming levels and get more expensive with the more assets they have to store, since it is all done offline and not dynamic!

Visibilty and Occlusion Culling work in this order from cheapest to most expensive:

  • Distance
  • View Frustum
  • Precomputed
  • Dynamic Occlusion (Hardware Occlusion Queries)

Instead of focusing on letting dynamic occlusion work start using Cull Distance Volumes to cull these actors that are not within range. This should always be used instead of solely relying on dynamic occlusion to do all the work. By reducing the number of actors that have to have their visibility checked by the gpu can help you better optimize your game!

We recently have made some new documentation pages for Level Streaming! These are a good resource to start working from to achieve what you want here.

Levels not to load when the game starts: control this via Blueprints and making sure the level is set to load via BPs, you can set up trigger boxes to do so. Having it set to Always Loaded means that it’s always loaded, so that’s why it’s there when the level starts!
Have the apartment level load when the front door is unlocked the first time: You can set a trigger box here to load. and delay the entry to the room for the load if it takes moment.
Have the apartment visibility turn on and off from a trigger or the level streaming volume (but only after the apartment is unlocked the first time): This can still be setup via BPs
Have all the items in the apartment continue to have collision even when they go invisible: If you’re using level streaming this isn’t possible since the level is removed, however, if you’re using Cull Distance Volumes, the visibility of the actor is removed but the collision will stay. This is fundamentally how they work, but just disabling the expense of the visibile part of the mesh.
Have items that are removed from the apartment not go invisible outside it: not sure what you mean on this one.

I tried other settings too. If I didn’t set it to “Always Loaded” the level would reset itself if I would walk away from the level streaming volume and then back. Doors would close themselves, closets that spawn items when they are first opened would reset themselves and then respawn the items when I would revisit the apartment (ending up in double items).

When levels are streamed in and out they are essentially loaded from their original state. If you need to keep track of the position or function of the actors that changed, like doors opening or items collected, you need to have an alternative method or have something that tracks these states and then updates them when the level is re-loaded otherwise it’ll be back to it’s normal state since this is not saved via the level streaming in and out.


Overall, I think a lot of your issues would be resolved if you used Cull Distance Volumes or setup a way to track the states for the actors in the levels that you want to be streamed in and out. Again, when streaming in and out the level it’s just grabbing a reference to this level and not saving its current state. If it did that, then you would change the level everytime you played and it would always be what it was last left as when playing.

With performance and keeping an eye on optimizing you also want to make sure that you’re using profiling techniques to identify where issues are coming into play.

Below are some good resources that should help you maintain performance and some additional tricks like loading levels transitions to wait for a room to load before entering.

1 Like

Thanks for replying.

Yeah, I suspected that might be it, but is there a way to see effectively what is culled?

I did follow that tutorial before but couldn’t get it to work and couldn’t see any difference in performance. I enabled Precomputed visibility in World Settings and tried messing with both the Visibility Cell Size and Visibility Aggressiveness as well as the placement of the Precomputed Visibility Volumes. Nothing seemed to improve FPS.

I will check out Cull Distance Volumes.

I followed that tutorial before posting this, too. But even there where it comes to the point about “Streaming Level Usage” it does not detail what each and every option means. They are very confusing to me.

I am relatively new to Unreal (started just the beginning of the summer). I am still trying to learn the “right way” to do things in Unreal. I am not sure how Level Streaming Volumes could be useful for anything but static worlds when they reset after time. I really wish there was more options there and in Level Details panel to for example allow the actors in the level keep collisions on when they go invisible.

Yeah, in my current setup I have the levels load from the ApartmentDoor BP. The door opening animation seems to be enough for the apartment to load.

Yeah, right now I hide/show everything that has their origin inside the apartment using a collision box on the Apartment Door BP.

Well, if there was an item that the player can carry in the apartment and I picked it up and carried it out of the apartment. With the level streaming system that bread would then go invisible as soon as I would step out of the streaming volume. When I was trying to search for clues about this problem I saw someone posting about the same problem.

Again, thanks a bunch for replying. I will definitely check out Distance Cull Volumes which are probably a lot more neat way of hiding the items than what I am doing now.

You can use the console command FREEZERENDERING to freeze the current state of things in the scene. This allows you to move the camera around the level and see if things are visible or not when occluded from view.

Precomputed Visibility has to be monitored in the stats panel. You can see better what’s going on by seeing when actors are not visible. Precomputed visibility is still more expensive than Cull Distance Volumes. There are also stipulations with it as well. The default cell height is 200cm. The default character is 192. So if you jump you are immediately outside of a cell and things will not be culled. Again, this precomputed visibility is more useful for mobile IMO to see the results. I don’t think this is the right way to go about controlling FPS. Sure it can help in controlled circumstances, but don’t look for it to be the end to any FPS problems. This is where profiling and knowledge about other systems comes into play to track down and optimize your game.

I’ve been working with Unreal Engine 4 since it was made available in March of 2014 and sometimes I’m still not entirely sure on the “right way” to do with everything. Sometimes it’s better to just jump in and learn the limitations of a system of tools and then solve the problems you run into. This has helped me learn the most that I have with the tools that I’m given. If I only focused on the “right way” to do something I wouldn’t push it to the limits and then learn how to dial it back or workaround the issues I run into. It’s really all just part of the learning process and I’m grateful for what I’ve learned because of it.

For the collisions going invisible this simply isn’t the case here. Level Streaming simply loads and unloads the level without saving them. It’s not just a matter of them going invisible. They are unloaded from your map. This is why you can’t have the actors in them still have collision when they aren’t there. Cull Distance Volumes keep the collision of an actor around and only turn off the visibility of the mesh. This is why when you grab an object that is from LevelB, as an example, and then walk away from that level so that it streams out, the actor that was part of that level is gone now as well because it’s been unloaded.

If you get stumped on Cull Distance volumes, the old UE3 documentation is still relevant. Granted the UI has changed, but the key features and information is there to hopefully get you a good grasp of what’s going on.

There’s documentation coming in the near future for Visibility/Occlusion Culling, Cull Distance Volumes, and Precomputed Visibility Volumes that has been updated for UE4. Keep an eye out! :slight_smile:

Yeah, I get that that is one of the settings, but with all the Level Streaming Usage options (SVB Loading, SVB Loading and Visibility, SVB Visiblity Blocking On Load, SVB Blocking On Load, SVN Loading Not Visible) I assumed it would also be possible to have Level Streaming Volumes only control the visibility and not loading.

Sounds good.

1 Like