Limbo, UE4 Level Streaming?

Can you use Level Streaming for a game like Limbo where you go the whole game without any loading or unloading?

I created a persistent level and then 3 steaming levels and tested but it does not seem like it releases the memory using the Stat Memory. How would you be able to tell if the level streaming is actually working?

I would hate to start creating all the levels only to find out later that this will not work, that you cannot have a whole game in one persistent level.

you can force call ue to do garbage collection.

streamed levels can be loded/unloaded. i’ve done that in the past with over 1000 levels. though you need to be careful with memory and object dependencies and lifecycle.

your title says ue4 ,but in ue5 you have data layers that can be loaded/unloaded, and worldpartitioning which is very helpful.
in fact world partitioning will do the whole load/unload/stream for you.

1 Like

Its possible to have just 1 persistent level. It does make designing easier, as it helps to conceptualize the whole game / level / world. Is it best practice? No. However, every use case is different. The limitations are more about the density of objects / actors in the scene.

If you have a huge map that is 1000’s to 10000’s of km, but the density of actors is similar to deep space (planets widely spread out), then its fine. Equally, if the map is smaller but more dense (think 10km2 to 100km2), as long as you limit the amount of actors in the scene, particularly Foliage and Landscapes, then you have options. Otherwise you may run into killer performance issues which will lead to continuous video memory / texture streaming pool type crashes. But you can always stream in smaller groups of actors anyway.

So the question is, what’s actually in the planned level? Generally UE is pretty hardcore at high mesh counts. It always has been, even before any optimization gets done. But large detailed landscapes or lots of smaller landscapes with foliage, will quickly test all that. :face_with_head_bandage:

1 Like

You can with world partitioning and data layers. But i am not sure about the availability and how well it works on UE4. which will also handle the loading/unloading. is pretty simple.

If you work with sublevels you CAN have them all loaded at the same time, or selectively. You have to enable the Levels subwindow (off by default).
the problem with sublevels is that baking light is annoying.

at that size ill check into world partitioning. keep in mind might also run into numbers running out of range. which i think world partitioning addresses a bit.

i honestly can’t make sense of this paragraph. i don´t understand.

ue has lots of optimizations, more than other engines. you should check them out.
afaik ue has “auto instancing” for static meshes that are the same mesh with the same material (or something there are some rules i do not remember, search online).
you can also look at using the hierarchical instanced static meshes too.
(static means they don´t change their world transform, but you can use WPO to animate them).
i’ll also check Nanite, since it can draw the same actor in one draw call given it has the same material (instance). but it does comes with some caveats, limitations, and performance hit too.

multiple landscapes? use the landscape tool of ue. it is already heavily optimized, and it has partitions and subpartitions only rendering the ones needed.
the foliage system that comes with the landscape system is also pretty optimized.

i’ll personally would try to get to ue5 and use world partition and nanite. since it will make the experience much more streamlined, smooth, and simple. it is actually meant to be used for big worlds so it handles all the streaming for you. (i’ve heard it has some hardware optimized asset streaming on ps5). it also has other things like keeping things in cache for when you turn around quickly.

For this kind of things Level streaming is quite basic. you still need to un/load things. and depending how you do it you’ll have frame drops, and dependencies. and unless you have a granular list of sublevels (and i mean granular. lots of work) or you dynamically create objects with some system that does that asynchronously and over time (neither of which are trivial to get right, even if you’re a good programmer), you will have frame hitches.

i do need to tell you that it sounds like you don´t have your expectations adjusted accordingly. if you plan on doing a game that does these types of things at such scale, you have to expect a considerable amount of effort to get it right, specially on optimization. on any engine. ue happens to have tools to help you but it will take time to learn and will not magically solve all your issues or work the exact way you want.
just because another game did it does not mean it did not came without pain.
i hope this does not sounds too harsh, its just my way of helping.

1 Like

You’re going into UE5 territory quite bit here though, and most of that may not apply (nanite on meshes / landscapes & data layers and so on). So have to assume from the title this is UE4 territory only for now anyway. Plus not all versions of UE4 support auto-instancing. :wink:

Yes, there’s still HLODs / ISM / HISM and so on, that can all be explored. But the OP is still building / prototyping. So how many of those options are ready to go out of the box without added work. Often those kinds of optimization methods come later on in the iterative process. In other words, you’re not always going to want to stop and look into all these options when you still don’t even know what’s going to be in the final prototype of the game. And that’s where my post is coming from. Essentially, you can throw 10’s of 1000’s of meshes at UE4 out of the box, even without auto-instancing, because the engine is a workhorse at static meshes. That’s always been the case btw since UDK anyway. :wink:

Whereas landscapes in UE4 anyway, are often quite a lot heavier. Personally I’ve never understood why identical landscapes serialize to *.umap as separate entities. Anyway, there’s 100’s of posts / blogs on optimizing landscapes. About how to get the most out of them or the best tweaks. But this all takes time and effort with difficult or not always obvious choices. And you want to be sure its going to be worth it all in the end, otherwise this approach while you’re still busy building, may just be distracting information overload. :wink:

Overall in any event, if you can create a single persistent level using mostly static meshes you’ll probably get good performance out of the box in most recent versions of UE4. UE5 is a whole different beast though. And optimization anyway is such a deep topic, how many of us really understand it all. :stuck_out_tongue_winking_eye:

1 Like

Limbo is not that big. You could get away with entire limbo in a single level where you use events to start and stop processes. In Limbo nothing really happens until you move into an area (people start running, physics start etc.) and that stops when you enter the next area. I’d not be concerned.

1 Like

Hey Roy, game_maker and Nande!

Thanks for the reply and I agree you probably could do it in one level.

I am programming for the PS4/PS5, I had made a game for PS4/PS5 name NextGen Sandbox and it was UE4 and had just individual levels which was pretty easy to do.

I was going to do the same thing with the new game which is a physics based motorcycle game, it is 2.5D kind of of like a combination Urban Trial Freestyle and/or Trials and Limbo/Inside, and I started thing how cool it would be to have the whole game one seamless experience like Limbo did.

Since it will be on the PS4 you cannot use a lot of memory so I did not think it would be possible to load all the assets for this game in one level. That is the reason I was thinking that the Level Streaming would work. You load of the “Persistence Level” which would not be a lot, just lighting and some blueprints with logic and then the first Streaming Level.

Now here is what I am not forsure of, just loading those 2 levels would not be much and easy for the PS4 but does Level Streaming work like that, will it only load the assets in memory for just thoise 2 levels?

Also, if you make your “Persistence Level” and then start adding levels, how big can you make it. This is a 2.5D sided, how long can it be made or how many levels can you add before the Unreal Editor starts lagging when you open the project and then try and open the “Persistence Level”

I have read a lot about how to setup levels and such but I could not find anyone who talks about real world how how big the game can be. During a live stream Unreal guys said they made huge “Persistence Level” for Gears of War with lots of streaming levels and for each ACT and then they would transition to another “Persistence Level” for the next act. So I guess Streaming Levels is really just to help make big levels and not whole games?

The reason I am still using UE4 is because of the Nvidia physics. They removed them in UE5 and replaced with their own built in Chaos Physics and when I tested them about a year ago they had all kinds of issues.

I’d call this 3D, with 2.5D I still think of Mario Kart 96 and Donkey Kong Country but that’s me. The sweet parallax effect of a few layers of moving 2D faking the 3D. What I see in Urban Trial Freestyle is more about 3D level building than having simple 2D with a backdrop like limbo. You’ll need more “asset” to fill that space but looking at that video they could easily load in few objects and reuse them constantly into different shapes (planks, car tires, industrial stuff). If it’s just variants of shapes you need you can also consider procedural generation or spline based shapes where you optionally load in 1 asset to make variants of, that lowers memory usage at the cost of processing speed.

Any assets you hold “hard references” to will be loaded into memory fully. Doesn’t matter if you actually use the hard reference. Even hard references nested in there get loaded recursively. What this means is that if you aren’t using soft pointers yet, do so. Those will allow you to load and unload assets into memory which would otherwise be in memory constantly. soft pointers do not load assets until you tell them to.

Usually when I have content that gets loaded / unloaded dynamically I set up a datatable containing soft pointers to assets. I swap in / swap out textures for keys depending on the input device used, by reading them from the correct datatable row. You’d use that to swap in / out assets used for level design like the limbo puzzle pieces / background art / bosses per area. It will be fine. If we are talking Limbo with the amount of content of Horizon Zero Dawn there is more to think of, but I’m talking Limbo :slightly_smiling_face: .

This isn’t answering your question about the level mechanics, but I find it difficult to imagine :slightly_smiling_face: . Limbo usually gets the balance right that keeps players playing, it goes back and forth between calm user exploration and running from death, showing some new mechanics along the way to spark curiosity. I have played Motorstorm and Trials Fusion which I liked but were quite exhausting to me. I think they cut up the levels in smaller pieces especially so you would not exhaust yourself and so you could get the highscores more easily. But my thoughts mean nothing without having played a prototype eh :slightly_smiling_face: sketch phase and prototype always comes before the details.

1 Like

Hey Roy,

Thanks for the detailed reply! Mario Kart 96 and Donkey Kong Country, wow those bring back great memories :slight_smile:

You are right, Limbo is a 2D game made with sprites and Box2D for physics, which is amazing to me what they did with those sprites and 2d physics, it was a masterpiece. Visual Effects in “Limbo” by Playdead
There is a documentary on YouTube about Limbo and Playdead and it is a fascinating story.

MotoTrials will be like “Inside” then, a full 3D game, (see pic below) but you can only move in 2D. I have heard of soft reference before but have never used them, it would be nice to load the level and then dynamically load content when you need it. I really had thought that is what the level streaming was going to do. I thought when you loaded the persistent level it will load whatever it needs for that level and then go check and make sure all the assets that it has pointers to are available but that is it. You are saying if you have one persistent level with 1G of assets and 10 sub/streaming levels with 1GB of assets each then it will try to load all 11GB of assets into memory?

I agree, a whole level like Trials Fusion would be exhausting. The main character in MotoTrails can walk, climb, run and you will be doing a lot with him and then he can also ride the bike. I am working on the prototype now, the physics for the bike took a lot of time to figure out.

Here is a link to Playdead blog talking about all different aspects to making Inside.

Some guy on Reddit made this full map of Inside, pretty cool.

1 Like

If at any time, you are making a “hard” reference to something, so a normal UObject pointer, not a soft one, then it is going to be loaded into memory recursively for anything “hard”. Even if your level manager handles some of this, you always need to be aware of it. Your UI, Datatables, asset properties, textures, sounds, animations etc, all must be soft when possible or a ton goes into memory.

That is awesome :slight_smile: you might enjoy parts of the ALS (Advanced Locomotion System) which is an animation framework for running , crouching and climbing. It has a free c++ version now on github and comes close to animation seen in Inside. Inside has some very pretty animation responses related to the scene intensity. Right after swimming, falling hard, escaping in Inside you see the effects. Love Limbo and Inside myself.

I think this type of “2D / linear” map is amazing for storytelling. I think one of the best map designs I have seen was actually Dark Souls 1, because you can always see parts of other areas in the distance that look entirely different from where you are. You can totally walk there through a different path and it really feels like a whole. You would be missing that in a true “2D” left to right map but I think that does fit really well with riding the bike. Another type of map design for “left to right” movement which felt surprisingly well you can find in Klonoa 2. It’s linear but some areas are curved and some areas offer vertical exploration and side areas. I see this combine rlly nicely with a Limbo / Inside / Trials combo

1 Like

I used ALS for the main character and you are right, it really looks amazing! The guy who made ALS went to work on the animations for UE5.

Started researching soft and hard references, it’s a whole new world, thank you for telling me about these and also thank you for telling me about the different games, I will check them out.

Doing some testing now with level streaming on the PS4 and will see how much stuff I can cram into a level before it crashes.

1 Like

Here is an example I wrote a while ago on loading soft pointers into hard ones:

Die to Survive - Railshooter - #240 by Roy_Wierer.Seda145

The example shows how to do this asynchronous. There are 2 ways of loading something. Sync and async. Async just means it is parallel to whatever you are doing so that you don’t block the entire game until it is loaded. It will load while you do other things.

Ok :slightly_smiling_face: . You can usually make an estimation but in the end very specific cases will pop up that kill performance and you can measure those in the debugger / profiler . I’ve had cases were loading 5000 pieces of foliage were fine, ± 400 static meshes (just cubes) screwed FPS until I put them into an InstancedStaticMeshComponent, and a case were a hidden main menu was screwing FPS because UE’s implementation of UI does a ton of cursor operations on invisible widgets. You won’t see it coming until it happens, then you fix it :slightly_smiling_face: .

1 Like

Hey Roy,

Did some testing this morning, added a huge sub level to the persistent level and packaged it for PS4 and then opened on the PS4 and the load time was the same before the huge sub level was added.

When the persistent level was loaded ran the Stat memoryPlatform command and it showed 1175 physical memory used which was the same before the big level was added, after triggering the big level volume the physical memory shot up to 2208.

So this confirms that level streaming is doing exactly what Unreal documentation says it will do and a full game should be able to be created in one streaming level as long as you have a beefy enough computer to handle all the levels being open at one time in the editor, that might be the problem with this. You might be able to make a huge level but trying to make a whole game may be too much for the editor.

Below is from UE4 documentation:
“The Level Streaming feature makes it possible to load and unload map files into memory as well as toggle their visibility during play. This makes it possible to have worlds broken up into smaller chunks so that only the relevant parts of the world are taking up resources and being rendered at any point. If done properly, this allows for the creation of very large, seamless games that can make the player feel as if they are playing within a world that dwarfs them in size.”

1 Like