One of the most frequent issues players complain about Planet Nomads is performance. Actually 30% of game refunds are attributed to performance issues or hardware requirements. This is from Steam Lifetime User Refund Statistics. Last month this number was 18%. And I am not mentioning bad user reviews because it's hard to count them.
Tuning the performance is always a dilemma. You we need to find a proper balance between sophisticated features or great visuals on one side and fast simulation and rendering on the other. Unlike consoles, on PCs you do not have one hardware we can tune everything for. So historically, we was adding new features without having any boundaries. And also not having fixed release deadline allowed us to count on help of Moore's Law. "One day it will be playable" was our mantra when we started the development of Planet Nomads. We wanted to focus on visual quality and endless possibilities and targeted on the best gaming computers. It did not seemed like a good idea to start by pruning everything from our ambitious plans to maintain 60 FPS on 2015 mediocre hardware. This is not the way we want the game to look like.
Now we want to change this attitude a little bit. We will take it from the other end and will not search for a computer capable of running our game, but rather set a reference hardware and tune the game to run on it.
Searching for a Reference Hardware
So, "60 FPS on Full HD" is our new mantra. But 60 FPS on what hardware? To wipe the difference between hardware configurations we have quality settings in options in the main menu. When we started development years ago, we purchased new powerful computers to be able to create and test the game. We still work on those machines, sometimes upgraded a little bit, and still cannot achieve stable 60 FPS on ULTRA quality settings on them. But this should not be a measure. ULTRA, a.k.a "not optimized" preset is meant to be little excessive to show nearly everything we can do. On serious gaming rig you should start on HIGH and lower it a little bit, if you are not satisfied with FPS.
So what is the "serious gaming" computer and what computer we should consider as a minimum? I looked at Steam Hardware and Software Survey for Planet Nomads and searched for most numerous values. I got a configuration like this:
Intel Core i7-6700K @4GHz
More than 12GB RAM
NVIDIA GeForce GTX 1060
1920x1080 (Full HD) resolution
64bit Windows 10
What does this say to us? Is this the computer that we should target on? No, I mean that this says: In current state you need something like this to play Planet Nomads. Maybe we could call it "Recommended by Real Players".
And even this is just the tip of the iceberg, the most frequent values, but majority of players have worse PC. And this say nothing about people who do not play Planet Nomads. So I think that we should look at the global Steam Hardware & Software Survey, not just Planet Nomads and search for configuration that at least 50% have not just the most frequent. At least for the "minimal requirements". And we should tune the game to be playable on this configuration. And when I say playable, I mean 60FPS on Medium settings, keeping Low as a reserve. So our 50% minimal configuration is:
4 Core CPU @3GHz
NVIDIA GeForce GTX 950 (or AMD equivalent)
1920x1080 (Full HD) resolution
64bit Windows 10
Originally, I wanted to use Pareto Principle and search for 80% configuration. It would be something like:
2 Core CPU @2GHz
Decent "Dedicated" Mobile GPU
1440 x 900 resolution
64bit Windows 7
I think that we should cripple "Low" setting to be usable on such machine. But I am not sure if it is feasible. It's under-recommended configuration and we should rather speak about something like 30 FPS on 1280 x 720 resolution here. It's hard to speak about mobile GPUs as they are very fragmented and it depends more on cooling and throttling of concrete model than on numbers in GPU datasheet.
From statistics we know, that 23% of Nomads play on Laptop. Planet Nomads is primarily a desktop game, so we cannot guarantee the best experience on mobile hardware, but we want at least the game to be playable. Our obsession in visual qualities can not be a barrier to play the game.
What to Optimize
There are two phases of optimization. First one we call Static Scene Optimization and it means that we select some game saves and load them on test machines. We try it on all quality settings and note the number on the FPS counter. We'll see how we could met the desired numbers.
The second phase will be Dynamic Game Optimization and it will be few minutes of real game play with flying over terrain, building blocks, riding vehicles, cutting trees, fighting animals etc. Maybe we will be testing it manually, but probably we will need some kind of automated bot that will play the game always the same way to be able to get consistent results. We will use average FPS or dropped frames as a main metric probably.
What is Already Done
In the meantime before we agree on the reference PCs and get them in our hands, as the configurations are still a subject of the debate in the team, we have taken our list of possible optimizations and tried them one after another on our development machines as a first step. Not everything proved to be effective, I'll elaborate more on some of them. The best ones are already incorporated in our development version and will be a part of the next release.
The core of procedural generation of planets is in highly optimized C++ library called Sandy. During profiling the game, it was a little surprise that 10% of CPU time is wasted in just one function - Perlin noise generator. But what else should a procedural game engine do than processing random numbers to generate nice environments? By setting computational quality to lowest we have lowered "perlin overhead" to 5% in expense of lower precision. We keep this solution as well as modifying all biome algorithms to use less complex noises to later stages, because it generates different and maybe "uglier" noises and will require wiping saves.
There are some tasks in game code that takes too much time and could not be completed in one frame. Typical example is animals path finding or save database operations. We use background threads in this case. Default Unity/C# implementation of threads tends to create new threads instead of reusing old ones. In typical scenario we have nearly 350 threads launched during first two minutes of gameplay. Not all of them was "our" threads, there are many of Unity's.
By implementing our own thread queue and pool we managed to reduce it under 100 threads, but there were no performance benefit speaking about FPS, as threads are very lightweight in case they do nothing. And because there were some bugs in low-level threading code we didn't put this into the final release. But we kept it for further investigation.
There is a popular technique on consoles that lowers the rendering resolution in case of temporal higher GPU usage. It is nearly unnoticeable and consist of real time measurement of FPS and adjusting resolution dynamically to prevent GPU spikes. The game UI is removed from this process and keeps at highest resolution. However on PCs it is not common practice and support in Unity is limited for PC builds. So we were not very successful in implementing Dynamic Resolution as we are not able to measure if game performance is currently CPU or GPU bound in real time in production build. So Dynamic resolution is rather experimental.
But we kept possibility to force lower rendering resolution in options, just for case of very low-end machines. That means some "ultrabooks" and other machines with a decent CPU but not sufficient GPU. Instead of reducing whole resolution, you can stay with native resolution for pixel-perfect crispy GUI, while reducing the GPU overhead by 25% 50% or 75% by rendering 3D objects in lower resolution. This feature is now ready for the next update.
Reorganising Cameras and Universe
The in-game world is much larger that what could fit into a camera and still keep the precision of rendering shadows etc. This is why we used multiple cameras. One camera to render large scale objects in distance between 2 km and the end of the world (sky, stars etc.) and the other one the near objects - everything nearer than 2 km. The two pictures is then combined together in image post-processing effects. There are also optional cameras for rendering water reflections and shadows on water surface. This approach is not very efficient, as our game scene si very complex and each camera takes about 2 ms of processing all scene objects before it starts actual rendering.
In new Unity 2018 there is a Reversed Depth Buffer also in Direct3D (it was introduced in Unity 5.5, but we have not updated from 5.4 before, mainly because all incompatible changes it contained) that allowed us to increase the reach of main camera to 20 km without quotable artifacts. And then move all the Universe inside this 20 km range from the camera and still make it look very distant. We have also removed some features like particle system for generating random star constellations and nebulae that was not visible at all.
This together means that if you disable water reflection, you have just one camera in the scene and in our testing environment we could increase FPS by +5% to +25% according to selected quality settings. This optimization is ready in our development branch and will be released with the next update.
Low Level of Detail Objects
For each game object we have created different models with different Level of Detail (LOD). This is very widespread rendering optimization practice. More detailed objects are slower to render and are used only if you are near the object. In contrary low detailed objects are faster to load and used at distance where you cannot see the difference. This switching happens automatically in the engine.
We consider LOW quality as the fastest possible rendering setting, so we decided to use only the worst LOD models in LOW Model Quality settings without even switching to better ones at any distance. This could gain about +15% FPS on lowest quality setting. This optimization is also part of current in-progress update of the game.
What Will We do Next
Now it's time to test new optimizations on real hardware, that means buying the reference machines and stress test them. But more important will be to maintain stable FPS during gameplay not just after the load of the scene, that means profiling and revisiting a lot of in-game scripts, forcing physics engine to run faster and searching for biggest CPU time eaters and memory leaks.
If you want to see if there is any performance improvement in your case, here is a little tip. In Quality options disable the FPS limit, try all the quality presets and notice the FPS after loading your save. You can use external tools to measure the FPS or open the game console by pressing shift+F1 and enter the "fps" command (without the quotes). You can than do the same after the game update of the game and let us know, if those optimization steps was steps in the right direction.
This week's update
We expect this update to be released this week and beside mentioned optimizations it will introduce new blueprint features and some new blocks, specially for our Kickstarter backers.