Over the years and with some specialized assets coming available, Unity has become a great tool for building games that require large open worlds. While these games still require careful planning and a lot of optimization, it has become much easier and faster to create the maps themselves. In this post, I want to share some tips and tricks that I have learned over the years.
I’m very confident this is the most important asset if you want vegetation in your worlds, and since it’s pretty much the only tool that actually combines a great workflow and amazing performance, I chose it as my first tip.
Vegetation Studio has a grass-creator built in, so you can simply use grass textures from megascans and convert them into lush vegetation within seconds. For trees, I’d recommend going with Nature Manufacture’s trees and vegetation packages. It’s possible to use Speedtree, however, I’d recommend only using Speedtree for ‘special’ vegetation and not to fill a whole forest.
You should use Instanced Indirect with every object that it works with, as it performs astonishingly. Only use the normal Instanced mode for shaders that don’t work with Instanced Indirect, and try to limit the normal mode to objects that you want to easily interact with.
Tips & Tricks
Billboards for Grass
While you should not use billboards for your normal grass, it might come in handy on special occasions. One time I was faced with the problem to create a large field of crops and I really wanted the player to be able to look a couple hundred meters over the field, which is why simply using fitting ground textures didn’t quite look right.
Instead, I simply told Vegetation Studio to treat the crops objects as trees (still with the usual grass shader though) and to create billboards for it. Once the billboards were generated, I baked them out so I wouldn’t waste processing power on hundreds of thousands of grass billboards.
As you can see by looking at the hill above the player’s head, the billboarding works perfectly and really emphasizes the scale of the crops field.
Some objects don’t react correctly to lighting when used as a billboard, so I’d recommend creating an alternate version of Vegetation Studio’s billboard shader and tweaking the color a bit.
You’ll definitely want to use IL2CPP and upgrade to Vegetation Studio Pro if you hit any performance bottlenecks. The pro version also makes use of Unity’s new math and entity system and will boost your performance to insane levels. Take this picture for example:
This part of the map features a ton of vegetation instances. There are up to a hundred trees in lod0 at many points, a lot of plants and other foilages to cover the ground as well as some objects like tree-trunks, sticks, and stones.
Overall this scene ran at about 70 fps on my machine (1080p, GTX1080, i7 6700k) before enabling IL2CPP, which is still not bad compared to other games, especially when keeping in mind what you get out of it visually. After I enabled IL2CPP I went to about 90fps (and also had many benefits with world-streaming). I then went ahead and upgraded to Vegetation Studio Pro and enabled the entities and math optimizations and was able to hit 130 fps in this scene.
Speedtree for special places
As I mentioned above I didn’t really like the performance drawbacks of speedtrees when used to cover an entire forest. While they certainly perform amazingly when used through Vegetation Studio, unlike in normal unity terrain, I still didn’t feel comfortable taking the hit on my time budget. However, speedtree works best when you want to give the user some special places to discover. For the map I was creating, I wanted the player to discover a lush grasslands area amidst forest on one side and the ocean on the other side. Speedtree was the perfect choice for this and really created that WOW-effect once the player popped out of the forest and into this area.
For world streaming, there are a couple of choices available, including creating your own streaming solution. However, the world streamer by nature manufacture worked well enough for me and I didn’t see any performance-reason not to use it. If you’re working with a team, you can simply select individual tiles of your map and work on those, while the other artists work on different coordinates. It’s probably not up to the task if you have a really large team of creators, In which case this article isn’t for you anyways.
Tips & Tricks
Multiple Terrain Brush
This is yet another tool from Nature Manufacture and it works perfectly with World Streamer. You can just stream in the terrains you want to work on, enable the brush and work on multiple terrains at once, painting heights and textures. It also helps to align the edges of your terrains perfectly so there are no gaps.
Ring streaming is probably the coolest choice as it helps you eliminate the cost of LOD calculations to a certain extent. I usually created an inner ring (4×4 usually) for the player to walk around in where I’d use normal game objects with LOD on them. I’d then create a middle ring where I’d stream in LOD3 so I could have a lot of distant buildings without having to worry about them doing expensive screen coverage or distance calculations every frame. For the outer ring, you could go with just terrain and Vegetation Studio, which I found to be fast enough, or go with a mesh terrain, which would grant you some performance benefits compared to unity terrain.
As you (can’t) see in this picture, the camera is positioned within the inner ring and normal LOD occurs on the objects within this 500m radius. The distant buildings are all placed on the middle ring at LOD3 (or the lowest I had available). This way they don’t do any calculations and I still can show buildings for extended ranges. After this, the distant hill behind the wind turbines is sitting in ring 3 and only features Vegetation Studio billboards (which is amazing since you can cover the entire thing with billboards at a minimal performance cost and it’ll look perfect).
Obviously, you will need to plan ahead, for example, if you want the player to be able to see extremely distant skyscrapers, you might want to create special rings for them.
Since World Streamer loads all the scenes it streams from disk, you will want this process to be as fast as possible. IL2CPP comes into play here and will turn a 1-second frame drop while loading a new tile into a very short (but still noticeable) frame drop. Which is why you shouldn’t forget to enable:
Prebake Collision Meshes
As obvious as it is, I completely forgot about enabling this and was getting rather frustrated since even IL2CPP couldn’t completely get rid of the small frame drops when loading a new tile. After some profiling, it quickly became evident that this was simply caused by colliders, which went away after enabling the prebaking.
At this point, my streaming was smooth enough to even fly a rather fast plane overhead and not notice any loading. Obviously, you could go with three-dimensional streaming, which World Streamer also supports, and have an even more pleasant flying experience.
Aura – Volumetric Lighting Effects
One thing that really helped to convey the size of the world and grant some depth to the scene as well as emphasize weather effects is volumetrics lighting. Aura is the perfect tool for this, it performed pretty fast in my tests, it looked great and was tweakable as well as easily controllable from code, and it is FREE! Really, give this one a try.
Not only is it possible to build huge worlds in unity, but it’s also really performant with the right set of tools. In my tests, I was able to achieve well over 100 fps average and not drop below 100 even in worst case scenarios. Your mileage may obviously vary depending on the other systems you got going on, like traffic and ai for example. The world building is really fast with World Steamer and even allows for small teams to work together. I don’t see a reason not to choose unity especially if you have limited manpower.
Below I’ll leave some more screenshots of the places I was able to create within just one (!) week.