Hi everyone.
I am working on some untitled game on UE4 and we are creating a world/map approximately 2x2km+ size and I have a few questions, just like you about your projects . So I created this topic for discussion âLevel optimizationâ
I watched epicâs videos about level streaming, hlods, impostors, fortnite optimization, and so on. But, for me itâs just âwe have such technologies, so try it yourselfâ and I tried.
So I have several solutions and want to share and discuss them with you (each line is my thoughts without practical use, only theory, because at the moment I am only studying cases for big-level optimizations and will practice in the near future):
World Composition - good thing for creating big/huge levels, for others World composition is weak tool (it has weak points with streaming, it can stream level behind the character. As I understand it isnât rendering, but it streaming in vram).
Level Streaming Volumes - almost the same tool as World Composition but with customizable Volume shapes for activating streaming, and has the above problem with behind the character.
2a. Currently I have almost created blueprint for Level Streaming levels which shown in frustum ±10 degrees. This is a simple method with simple math.
LOD - probably everyone knows about it, but I will write: LOD - level of Details, load levels depending on the distance from the character
HLOD - usually the same as LOD, the difference: LOD is one mesh/object with own textures, HLOD combines meshes/objects into one large object and creates an atlas to reduce drawcalls. In UE4 it is
generated automatically. In my âideal worldâ it must be created by human or half-automated. Yes - it cost a lot of time, but the result will be better than automatically. And we want to achieve the best result in game, am I right?
Impostors - an old topic, but unfortunately it is often forgotten. Need additive sheet-texture, but fewer vertices, reduce drawcalls.
I going to try the following scheme:
game logic, collision for the whole world (because we can throw a grenade far and it is multiplayer game), sounds, general light in separated layers using 1. World composition
level streaming with 2a
lod0 for first zone (closest to the character camera)
lod1 for second zone
lod2 for third zone
hlod0 from lod2 objects + impostors for fourth zone (mainly to reduce drawcals because the atlas)
hlod1 from lod2 objects + impostors for fifth zone (To Infinity and Beyond!)
What do you think about this?
P.S.: if I make a mistake somewhere I will be glad to hear where I am mistaken
Big thing to watch out for with UE and open world stuff is the time spent adding objects to the world. We expected our levels to be dominated by IO â ie, by getting stuff off disk and streaming it in. As it happened (UE 4.13) it was the lifecycle costs of the things coming into the world â making UObjects for them and adding them to the world, and even removing old ones from memory â that really killed us.
Have not run the same tests in current unreal but Iâd expect thatâs going to be the real driver, so do a bunch of testing with somewhat representative content early. It was an unpleasant surprise for us!
Yellow - StreamLevelIn, loading into memory, no rendering
Orange - StreamLevelOut, loading into memory, no rendering
Green - show level
Dark Green - hide level
This currently saves 20-50% of memory.
Can someone share a link to the explanation/training of the UE4 Session Frontend -> Profiler ?
Because I canât find a good documentation, everywhere âthere is profiler and it can give you different CPU/GPU statsâ
I interested in that hell-shell, a lot of events but almost each event has CPU Stall - Wait for Event with âbig ms numbersâ and it is REDed and different other âmagic for meâ things (the picture just an example)
Amazing! Iâm facing the same issue of many CPU stall when levels are streaming in, so could you give me a brief of how to find the real bottleneck? Thanks~
I donât have a running unreal at home for the holidays, but I seem to remember that the magic words are âadd to worldâ or some variant of that â itâs the UObject lifecycle management that is (or was, last time I looked) the real killer
CPU stall -> CPU is just waiting waiting for something⊠and it can be anythingâŠ
I looked through all the stats and in my case the bottleneck was Garbage Collector, so if your âgame worldâ is less than 10x10 km and each object in the game isnât unique I advise you to turn off GC:
in project settings set +100500 sec for âTime Between Purging Pending Kill Objectsâ . It generate more minuses (game freezes) than plusesâŠ
set s.ForceGCAfterLevelStreamedOut 0
set s.ContinuouslyIncrementalGCWhileLevelsPendingPurge 0
If a game session lasts more than 10 min you must create your own rules for Forcing GC to save memory
The second bottleneck was occlusion (stat initView). You should consider streaming as a tool for working with occlusion (because it is expensive for the CPU)
Next was - World Tick Time. Use as few ticks as possible, use more timers instead ticks
and next was - loading some c++ libraries during a game session, instead of preloaded it (in my case, the first grenade throw initiated the library loading ⊠and the grenade throw could happen for example in the 4th minute of the gamesession)
And as mentioned @Theodox âadd to worldâ is the hell of streaming (look for AddToWorld() )
P.S.: sorry if I forgot something, but this is a very big topic for discussion, where there are a lot of variables for making this or that decision. As I was asked at one of the interviews âwhat is better, large or small particles in the screen?â ⊠there are a lot of unknowns to give the correct answer (but they didnât like my reasoning with the arguments of the first and second cases, they expected a clear answer âbig or smallâ)
thanks u so much! your advice inspired me a lot and i now know this is a complicated issue. i found my game has a mixing problem consist of big texture loading, gc hitch, and even navigation system bug. I am step by step fixing them now
i understand from you that you can stream levels that are in yellow area . and that look impressive and good for optimization . but the question is how can you do that in unreal engine .
when u say StreamLevelIn , you mean by level meshes and objects or sublevels or what