Before making a new map, one should consider all of the issues brought up below.
Streaming Distances
Occluders
Camp placement
Best practise for laying out a map is to include creative leads, artists and designers. The more planning the less surprises later on, and the less confused the map will be. In addition, problems with streaming distances can easily be identified early on in this process, being taken into consideration and fixed before work is even started on the map.
It should be mentioned that this page in no way is a complete guide to map-making; the point of this page is to look at maps for the sake of streamlining and optimization.
All levels have Levelbounds. The level bound helps determine the shape of a level and by default, the levelbounds is a rectangle that automatically adjusts itself to contain all actors inside itself. This bounds then helps determine the streaming distance of the level.
As soon as a heightmap is generated, but before putting in any additional assets into the level, the AutoAdjustLevelBounds should be set to FALSE .
The reason we do this is to prevent the level-bounds to inflate after placing additional meshes and actors into the level that may go slightly beyond the bounds of the level. We need to keep this in mind, since the heightmaps are not the only source of actors. The Persistent level, wildlife, camps, audio and additional gameplay levels may span large areas of the map, which contributes to the amount of actors that need to be loaded at the same time.
Below is an actor count for the Persistent Level alone.
Streaming distances should be set up as required by the map; if a heightmap is exceptionally tall and can be seen from very far away, the streaming distance may need to be set to be further than normal - likewise - if a heightmap is tucked away and very hidden, the streaming distance of such a heightmap can be set lower than normal. We will talk about this later.
When placing camps, the size of the camp needs to be considered with the streaming distance in mind - see more about this later.
Huge camps with many assets should be at such a distance that two of these camps do not load at the same time. The streaming distance of heightmaps determine this. On the Isle of Siptah, the streaming distance is 1km as are the heightmaps, which means that huge camp levels should be at LEAST 3km away from each other.
The reason the big camps on Siptah are as close to each other as they are is rooted in another level-design problem, which is the setup of allowing players to spawn on both the West and East side of the island, thus compressing the gamespace significantly. That aside, let's look at the distances on Siptah for these camp-levels:
As we can see, the distance between where these camps reside is very short (in comparision to the streaming range). In particular, the location of the middle camp is very bad, since it loads the heightmaps that contain all three camps at once. A reduced streaming range for levels would help here but ideally, these things should be planned out much better in advance (when the level is designed, not afterwards)
Wildlife levels have, in the past, been rather large. This is because wildlife such as elks, deer and rabbits don’t come in clustered populations; instead, they are spread across the map to provide a base level of wildlife and immersion. Wildlife are also using a specialized AI setup that means that, performance wise, they are much better than NPCs that have combat.
Level-bounds for PREY should ideally not extend much further than a single heightmap.
Level-bounds for clustered enemies, like crocodiles, rocknoses, and so forth, should be given their own levels and their own level bounds in order to allow the engine to stream these enemies in better.
This is an example of a PREY wildlife level (the smaller rectangle is the wildlife level, the larger one is the heightmap):
Example of clustered enemies in their own separate levels
Levels, when created, are set to have a specific Streaming Distance set up. By default, the streaming distance is set to "Unspecified", which is 50000 units (500 meters).
Streaming determines the range at which a level starts loading in on the server and client. All actors inside a level is loaded into memory when this is done, and so keeping heightmaps as clean as possible is imperative.
The fewer unique assets (meshes, textures, monsters, sounds, etc), the better the memory profile of any level will be. Since multiple levels are streamed at the same time, all actors from all these levels are loaded when players enter the streaming bounds of an area.
As an example, let's look at the streaming range for Siptah heightmaps.
All heightmaps on Siptah are set to have a streaming distance of 100000 (1000 meters, or 1km).
Each heightmap is 100000x100000 (1km by 1km). With that, let's take a look at what happens.
It's very easy to assume that the situation would be as follows (the red lines are 1km in length, and centers around the character):
This is not the case. When loading the center heightmap (X3_Y3) in Siptah and pressing play, we can see what is ACTUALLY loaded, which is as follows:
The reason for this is that streaming distance is not measured from the player to the center of the heightmap, it's measured from the edge of the heightmap to player. What that means is that the heightmaps that are 1km by 1km large have an additional, invisible streaming distance border that is 1km away from the heightmap, and if the player is within those bounds, the heightmap begins to stream.
As we can see in the explanation image below - this is why heightmaps that are very very far away from where the player actually is, are still being loaded:
Not all is doom and gloom here, however. While streaming in levels from huge distances like this is very bad, it's not quite as bad as it looks. The engine will not activate assets that are completely outside LOD range, nor will it render everything at the same time. It is still very bad though.
Best practises for heightmaps is to not be rigorous with the setup of these distances. If a heightmap is absolutely required to load at a long distance, then so be it, but that heightmap should have as few unique assets set up in it as possible to reduce memory cost.
Use Landscape LODs instead of streaming levels at a distance. Landscape LODs reduce the memory overhead significantly.
If specific, unqiue features in a landscape are visible from afar, consider splitting these features up into another level and putting the streaming distance for that level up instead of using the entire heightmap for this purpose. An example of this can be seen in the image below, which is from the mod "Savage Wilds", where optimization HAD to happen because mods must not go beyond 2gb in size or they won't work.
The Exiled Lands have a streaming distance of 50000 (500meters) and works marvellously fine with this. The reason for this is that there are no locations in the Exiled Lands that require the player to have a huge view distance with the exception of the Volcano, which has levels set up with this in mind. Looking at the Exiled Lands from a side-view, it becomes rather apparent why:
The Savage Wilds uses the same method of occluding although even more aggressively, since it cannot use LODs.
The Isle of Siptah design is such that the low, central plains provide no occluders for when players stand on top of each of the west/east plateaus.
Keep the folder structure organized. This is helpful not just to you, but your fellow team-mates as they work on the project.
This is an example of very bad folder organization:
This is much better:
It doesn't matter what the folder organization IS, as long as it's followed by everyone.
Tips :
You can use groups to copy and paste designs, but once these are finished, ungroup your assets and put them into a folder instead.
Keep the file folder convention the same for all levels (camp levels and heightmaps should use the same file folder structure)
The suggested folder structure below goes for Camp and Heightmap levels, it does not include audio or the persistent-level, as these require much more organization.
Cliffs/
Rocks, cliffs, other larger things like huge trees
Water/
Watervolumes, navmesh modifiers, underwater postprocessing
Camps/
Gameplay_Xx_Yy/
Population/
Spawnpoints, TerritoryManager, CampOwner, Loot-chests
Props/
Decorative meshes and actors
Interactables/
Stand-alone Gameplay elements that require interaction (lore, feat-teachers, etc)
Landscape/
Heightmap
Levelbounds
Cinematics/
Cinematics
Volumes/
Specialized post processing volumes
SpecialPropertiesVolumes
Audio volumes
Blocker-volumes
Camps should exist in both the heightmap level where they are placed AND in their own levels. The purpose behind this split is that we want players to be able to see the camp at a distance but not have to load the entire level for the camp.
Place camps in such a way that it’s possible to surround them with occluder walls. These walls can be cliffs, mountains, opaque barricades or large ruins.
The only camp parts that should be put in the heightmap levels are actors that CAN and SHOULD be seen from far away. Everything else should be in the camp level itself.
Gameplay levels that are very big should be split into sub-levels. Each of these levels should be as separated as possible to reduce memory overhead.
Do not overuse assets. We have the ability to instance meshes but an overabundance of meshes still contribute to drawcall amounts. In addition, Many of our assets can be creatively put to use to construct shapes without the need of additional meshes.
However - do not overuse the amount of meshes in order to cobble together new and fanciful constructions. If your construction consists of anything more than 5-10 assets, you should consider asking an artist for a custom mesh for this instead.
Use large props to fill space
Pet pens, altars, walls, tents, wheels of pain, etc
The image below is a great example of using large assets to your advantage
When setting up a camp, one of the most common mistakes is setting the CampOwner actor up wrong with the CampBlutility.
CampOwners should only contain:
SpawnPoints
Waypoints
Loot Chests
BP_CA_xxx assets
And should never contain
Anything else , including
Standalone blueprints such as the “Relic”
Static/Skeletal meshes
When working in a camp, it’s very tempting to make use of unique assets to give an impression of unique visual styling - but doing so increases the amount of textures and meshes that need to be loaded in a camp. When making a camp it’s better to use assets in a constructive fashion rather than heave as many unique assets into the camp as possible.
Instead of placing multiple swords with different meshes on a single table, it’s fine to just use a single sword.
Instead of placing a suit of armor on an armor-stand, you can just use one of the pieces
Instead of using different jugs and jars, plates and cups, decide on one. This also helps instancing them.
Instead of using all the different varieties of planks, consider simply using one or two instead
Instead of using every single variety of impaled skeleton spike, use a few of them instead and rotate them to create more variety.
8 Assets were used to produce this scene, 5 of which can be instanced (The house, decals and awnings can not be instanced - and only because we only have one of these houses here)
Compare that scene to the one below, that uses 21 assets. Yes, it looks nicer but several of the assets only appear once (12 of them in fact) and all the player sees is “clutter”
Camps can be, but doesn’t have to be, visible from a long distance. In the cases of camps that ARE visible from a far distance should make use of Hull-levels (see Optimization Procedures ).
Camps that do not have hull-levels should be planned out ahead of time so that they can be occluded by cliffs or other occluders.
Here is another example of a smaller camp - this one is perfectly occluded:
Below is another example of a camp surrounded by a wall, this time broken up more with wooden walkways
And finally, we’ll look at a camp where occlusion hasn’t been thought about much (if at all)
Looking at the examples above, it’s clear that it’s very possible to create occluders without needing a hull-level but it also shows that camps we have that are visible from far away could make use of hull-levels to their advantage. No camp is ever bigger than a heightmap, after all.
The guidelines here go for both camp and heightmap levels.
Note: This page is not meant to deal with how to use the instancing tool, merely what it should be used for.
The instancing tool allows us to instance meshes. It is, however, limited. Do not use the instancing tool for
Transparent objects
Skeletal Meshes
Meshes with negative scaling
Meshes that are single meshes already
Meshes that exist in different levels
Meshes that are too far away from each other
This is by far the most common example of bad use. Instancing reduces framerate costs but if used wrong, can in fact INCREASE framerate costs. To that point, we will cover proper instancing below.
Instancing should be done when multiple of the same meshes can be seen by the player at the same time. Examples of this could be:
Multiple books using the same mesh in the same book-case
Multiple rope-knots forming a connector-point between two planks
Multiple crates piled on top of each other
Mugs and pottery placed on top of tables
However, as mentioned before, bad instancing leads to worse results, and so let’s look at a few examples.
In this case, both the outer and inner walls of this barricade have been instanced together. This means that even when you are on the outside of the wall, it will render the inside walls. These should be instanced separately.
In this case, the instancing here is obviously bad since it’s almost impossible to view all these wall sections at the same time. However - in this case, it’s also symptomatic of another problem - overuse of different assets. If all these wall-pieces had been the same, it would’ve been trivial to instance the wall sections in groups rather than doing it like in the image above.
In this image, we can see that the entire road leading up towards the stair-case has been instanced. Sections like this are tricky, because it’s likely that you spend just as much time looking at only half the assets as you are looking at all of them - however - in this case, the distance of this section is small enough to allow all these to be instanced together. This IS a judgement call and there are no hard rules.
The bags and the woodpiles in this image are marked, but the barrels are in fact also instanced. This is a good example of instancing and works very well.