Blog

Captain’s diary #15: Beta build optimizations, 2-3x increased FPS, and nicer screenshots!

Hello everyone, Captain Marek here. In today’s edition of Captain's diary, I’m going to cover our latest additions into COI beta.


Optimizing rendering

Initially, we were not planning to do more patches for Beta, but we saw that some of our beta players built such large factories that the game was becoming unplayable (single-digit FPS in the most severe cases). So we asked our Discord community to share with us save files of large factories and got around 10 submissions. Thanks, everyone!


Thanks to the provided save files we were able to quickly identify what is causing the largest FPS drops. We wrote a script that selectively disables certain parts of the scene and measures impact on the FPS. This is what we saw when we zoomed-out to see the entire factory:

​ Baseline: NoTerrain: NoTerDetails: NoWater: NoWaterRefls: NoTrees: NoSettlement: NoPorts: NoTransports: NoTrProducts: NoPillars:

​8.04 FPS 8.26 FPS 8.30 FPS 8.27 FPS 8.32 FPS 8.47 FPS 11.6 FPS 8.62 FPS 8.94 FPS 8.12 FPS 12.2 FPS

As you can see, transport pillars were by far the largest offenders followed by settlements. It turned out that as pillars and settlements are composed of many smaller sub-objects the overhead of managing and rendering them in Unity becomes unbearable.


Transport pillars optimizations

To improve transport pillars, we used a technique called “GPU instancing” that allows rendering of multiple objects in parallel. We already use this technique for some other things in the game such as grass or products on transports. The hard part is that we need to do all of the bookkeeping ourselves since instanced meshes are no longer objects in the scene. Turns out that pillars have 40+ different variants of meshes making bookkeeping quite complicated.

There were some issues when implementing GPU instancing. Bookkeeping things in compact arrays can be tricky!

However, once everything worked, the results were worth it! Rendering time of the transport pillars was decreased by 8-20x, nearly doubling the FPS of tested scenes! This also reduced the number of individual objects in the scene by half! Would you think that half of the objects in a factory were pillars?


Settlement optimizations

Next one on the list were settlements. Some players were reporting earlier that they get FPS drop when a settlement is in the view and they were right! The issue here is very similar to the pillars – too many small objects. But the optimization used was completely different. Settlements have many objects because they are re-colored on-the-fly once the player places them down, so that they are visually distinct.


The solution was to combine individual meshes after they get colored, one mesh for each color. This process has to be as fast as possible to avoid introducing lags and we were able to make it work in ~10 ms per settlement.


The results of this optimization were even more impressive than transport pillars, a whopping 200x faster rendering of settlements that went from ~40 ms to 0.2 ms! And the total number of game objects in the scene dropped by 20%. That all means no more lags when looking at settlements!


Water reflections

We also looked at the impact of real-time water reflections that were introducing 5-15 ms of slowdown per frame. We decided that the effect they provide is not worth this cost so they were disabled for now.


Optimizing simulation

Rendering was not the only thing that got optimized. We also looked at the simulation code. I won’t go into too much detail here, but some of the big gains were from eliminating “useless” calls. For example, every storage and every transport connector were being tested for electricity even though none of them required it. Or every transport pillar was being updated but its update method was empty.


Such inefficiencies come from object-oriented approaches where the base class implements functionality that may not be used by all derived classes, which turns out to be a bad pattern in this case and we are working on refactoring it.


We have also introduced a performance optimization for chained storages making their simulation run 3 times faster.


The gains from these efforts were quite significant, simulation is ~30% faster and synchronization between simulation and rendering runs ~50% faster.


Nicer screenshots

We’ve noticed that screenshots captured in-game sometimes look a little pixelated. This is caused by a lack of anti-aliasing (known as SSAA or MSAA) since the rendering pipeline we use does not support it. In the game we use temporal-anti-aliasing which helps a lot, but that does not work well for still images.


To make screenshots look better, we have implemented a new capturing routine that renders the game at a double resolution and then scales the resulting image down, smoothing any pixelated edges. Yes, it is that simple and the results look great, see below! So the next time you want to snap a screenshot in game, use the Photo Mode (F11) to get this benefit!

A 2x enlarged view at a screenshot captured with and without the new technique. Notice how terrain is not affected since it has no edges.

Bridges

We have also added two extra tiers of bridges with more space under to provide more flexibility for your transports.


Early access

We are also working on early access. We are redesigning several areas that would be harder to change in EA. Some of these areas include - food diversity, recycling, improved health system. We still don’t have a full roadmap for EA as things are still unfolding (e.g. we got a bit distracted by the performance work). We also got prototypes of new liquid and loose storage units, which we will hopefully share soon.


Update from the community

In the previous Captain’s diary #14 we have introduced a new timelapse tool and a Discord user zytukin decided to completely FLATTEN the largest map with their fleet of excavators! This map is called You Shall Not Pass and I think you passed, zytukin!


A timelapse of flattening the You Shall Not Pass map, shared by zytukin.

And that’s all we have for now. Take care and see you in our next update!