Map Design Best Practices

Map planning

Before making a new map, one should consider all of the issues brought up below.

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.

Levelbounds

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.

Level-bounds for heightmaps

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.

Level-bounds for Camp and other gameplay levels

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)

Level-bounds for Wildlife levels

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.

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

Streaming Distance

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.

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.

Optimizing Streaming Distances

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.

Plan the level-layout ahead of time

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.

While making a level

World Outliner Folder Structure

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 :

Suggested 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.

Making camps

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.

The image below is a great example of using large assets to your advantage

CampOwners

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:

And should never contain

Limit the use of unique assets

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.

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”

Framing a Camp (a.k.a "How to make visual blockers")

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.

Instancing

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

Proper use of instancing

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:

However, as mentioned before, bad instancing leads to worse results, and so let’s look at a few examples.

Example 1 - Bad instancing of walls

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.

Example 2 - Bad instancing of walls

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.

Example 3 - Good instancing of ruin floors

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.

Example 4 - Good instancing of props

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.