A month later, time to finally have a new dev blog. This time brought to you by our main man, schema ...
A number of players have expressed interest in hearing a bit more in-depth on things like how we optimized our turrets in the recent update. Well in order to best cover how we improved the performance of some aspects of StarMade I’ll be writing a series of Dev Blogs explaining some of the difficulties of building a game like ours, and how we overcame those difficulties.
Physics for any game are probably one of the most important aspects. There is a lot of code and effort put in game in that alone. There are a lot of brilliant libraries to use already, but depending on the game you will also have to manually customize to get the best results.
There are several points to consider for physics:
- How big is the world?
- How many collidable objects does it contain?
- How many objects are moving?
- How detailed are the objects?
- Do the objects’ shapes change?
If StarMade were to try to run in a single huuuuge sector, you would probably be lucky to get a frame per day on a bigger server.
To combat this humongous task, one of the prime mantras of programming is used: “Divide and conquer”. This means, a big problems can to be “cut up” into smaller problems which then can be handled more easily. Also we have to identify what we don’t need at all times (like a sector where nobody is at the end of the universe).
Relatively early in StarMade’s live, the sector system was introduced. I’m now glad that I did it that early, because the more that complexity is added to the game itself, the harder it would get to do it afterwards. The sector system helps divide up everything, from physics to network load.
As a few of you have noticed with MC and other games, a game’s world can only be so big when using a single “sector”.
Most games usually use floating point numbers to define “where stuff is”, and that includes basically every polygon in the game. There are 4byte floating point numbers which are normally used, but because you can only fit so much into 4 byte (32 bits), due to the nature of floating point numbers, the precision (amount of decimal digits) decreases, the higher the number itself gets. This means, that numbers in the one million area have much less decimals than numbers between 0 and 1.
For games in a bigger world this means the world is going to get buggy at a certain range, as all positions of the polygons and whatnot get very imprecise, as well as all math operations done on these.
The easy way out for this is to just switch to double precision values (8 bytes), usually called ‘double’, which doubles the range in which values are precise another 32 times (which is incredibly huge).
However, this method has a very deciding downside to it: Every single number will take double the space in the computer’s RAM, the graphics card’s RAM and on disk. Not only that, but also all that data has to travel from the different parts of a computer’s hardware, and there is only so much that can travel at the same time. This alone would be already be a major downside, but one thing that doesn’t grow as fast as other things in the computer world is a user’s network bandwidth. Using double means you have to send double the amount of position data for every object in the game’s world, and position data is the biggest thing that is sent and received constantly.
StarMade’s sector system gets rid of that problem completely. Not only that, but by constantly monitoring which objects are in which sectors, we know exactly what areas we want to update, and where currently no active or moving object is. This means a lot of so called overhead can be eliminated, because we don’t have to look at every object to check if it’s active or not.
One of the biggest physics advantage of having sectors are two things: Objects that are not anywhere close in terms of vicinity don’t have to ever be tested for collision or even distance to each other, and the limited sector range speeds up the so called “broad phase” of physics.
Physics engines usually comes in 2 phases. The broad phase, in which an area is scanned for all the objects that can possibly collide. To do this, axis aligned bounding boxes are created, that means, a box around an object that is always aligned to the coordinate axes of the geometrical system. There are several methods to check which bounding box overlaps with which, the slowest being brute-forcing: meaning, testing every object with every object which gives us a whopping complexity of n^2 tests that have to be done each time. A n^2 is usually unacceptable if you want to have anything that remotely scales.
The method used in StarMade is the physics engine’s axis scan. Imagine it like a 2D plane that moves from the back of the sector to the front. The complexity of that is n*log in the worst case, which is a LOT better.
After the broad phase is done, we know which objects possibly collide with others. So now a more detailed test for each pair can begin: the narrow phase.
I will cover that in the next part of this blog.
Thanks for reading,
schema