LifeStampGames

Bringing Data to Life

Double Precision Space Game Development

One of the original inspirations for this game came from a scene from the first Alien movie in 1979, I actually found a screenshot of it below:

The path created by the squares drawn in space was awesome; I originally intended a game that starts the player some distance away from the target planet and the goal was to enter orbit. After much fussing, I came up with this prototype:

This thing was kinda fun to play with but I found actually entering a circular orbit to be nearly impossible; the velocity has to be just right at the right place. So then I realized I needed transfer orbits, and started reading up on math that would kick be all over the map for roughly the next 6 months. The first step was just creating two circular orbits around the planet and an elliptical one between them. That only took a few weeks, and it worked pretty well. Here's a screenshot view from far above the orbital plane:

If the player was in the outer orbit and hit the brakes at the right time - the transfer point in the upper right, the player would fall towards the planet, then another reverse burn behind the planet at that transfer point put the player on the circular orbit I was looking for. Close enough that you can see the planet on the edge of the screen.

In theory I could stopped here and made a little app that challenged the player to transfer from the outer to the inner circular orbit. Then I started thinking more about what you would do transfers for - to explore some object in space like we do now, or what about mining asteroids? Actual transfers take months to years, and reading lots of stuff on simulating this for a game provided lots more challenges to deal with.

First, I added the inner planets and moons, and found myself wandering away from the game path to go explore the moon:

It happened so much that the thing needed a whole second half in the form of a simulator to let players explore unrestricted. Anyway, that is a whole other branch of development history.

After more months I was able to successfully draw 5 orbits from Earth to a target asteroid that aligned perfect at tangential transfer points. The math took some serious time to work through, luckily someone had already started for me here : http://clowder.net/hop/TMI/TangentEllipses.pdf (thanks to David Hollister author of PDF, credited in-game). I modified this stuff somewhat heavily but was psyched when the big transfer orbit from earth to the target asteroid was drawn correctly. It's difficult to show all orbits at once because of the scale, even in-game, but here is a page from my heavily used notebook that shows the top half of the big transfer orbit and both orbits around Earth and an asteroid. It looks like owl eyes.

So many challenges...my plan all along had been to scale the solar system to as large as I could, and of course ran into floating point precision problems. When you got close to the target asteroid, it jittered around quite a bit. Lighting would flicker in weird places as well. Reading up on this all over the web I removed the Unity physics engine and every orbiting body now managed its own local position within the solar system using double precision. The guts of it looked like this:

public Vector3d myPosition;
public Vector3d myAcceleration;
private Vector3d myVelocity;
public double myMass;

void FixedUpdate() {
  myAcceleration = (_force / myMass);
  myVelocity += myAcceleration * Time.fixedDeltaTime;
  myPosition += myVelocity * Time.fixedDeltaTime;
  transform.Translate ((Vector3)myPosition - transform.position);
}

The Vector3d libraries are available here: https://github.com/sldsmkd/vector3d

To deal with the flickering lighting I changed the player from moving to always at the origin and the solar system moves around it. After much more messing around, I was able to get a solar system scaled to a maximum semi major axis of about 100,000. The asteroid was stable and using a double precision gravity force from the sun it would orbit in its ellipse for a while before going out of orbit. Annoyed, I did more research and found that even with double precision, just like (apparently) in real life circular orbits often degrade into elliptical. Ugh, reading more I decided to make orbiting bodies' motion in game play deterministic, or following a pre defined path. The easiest way I found was to keep track of an angle of each orbiting body, and then each would calculate its own position using double precision like this:

transform.localPosition = new Vector3 (foci + Mathf.Cos (angPosRad) *
  (semiMajorAxis), 0, Mathf.Sin (angPosRad) * (semiMinorAxis));

The only thing that changes in the above over time is the angPosRad, which is calculated based on the orbiting body's period of rotation. I even decided to animate the transfer orbits - change them for every position the orbiting body is taking - which is shown in the asteroid selector in-game.

Now, so after all of that, I had planets and moons orbiting at large scale, grudgingly deterministically (although I saved all the gravity based code to use for the simulator). Now I set about to change the time scale of the large transfer orbit to max out at 100. that way users could experience a scaled solar system but not have to spend months drifting under the sun's gravity to play a game.

Except the frame rate plummeted at max time scale. I optimized the heck out of it, reducing mesh colliders and only turning them on when nearby, reducing textures and lighting. I could only get about 10-15x max time scale before it became unplayably laggy.

So, after all that damn work to support large solar systems, I had to cut the thing way back for the game. Additionally, I cranked up the gravitational constant so things would be faster, again you reach a limit with so many things flying around. To get close to the right speed during the big transfer, the orbital speed around Earth and the asteroid was unplayably fast. After many more months, the fix I came up with was to use a different gravitational constant for each of the patched conic sections. The kicker is that the "sphere of influence" distance, within which an object can be captured as a moon, had to solve for the distance at which the forces from one gravitational source are equal to that of the sun but each with its own G. After much tweaking I was able to get the thing to use speeds that seemed reasonable.

The scales are all whacky for the game, but for the simulator everyone was normalized and changeable by the user - the scales are shown during re-scaling.

With deterministic positions, I found that getting the player to start in low earth orbit was tricky; the deterministic speed had to be just right and even below or above it was challenging. Re-drawing the big transfer orbits every frame or every nth frame also took a toll on the framerate. I tried other libraries, like Vectrosity, but in-game performance testing showed the Unity Line renderer was a bit faster, consistently. But still not enough to support full motion transfer orbit calculations every frame.

The only real solution was to remove the motion of the orbiting bodies altogether for game play. Damnit! After all that work! Lesson to self about thinking things through...ahem...anywho. Once everything was fixed, only game loading took a bit to draw the transfer orbit and then the framerate was much more reasonable.

After testing playing for a while, I added some obstacles and power up coins and such, but really it needed something else. Even though real space missions don't do it (as far as my nube ass knows), I tilted the entire orbital transfer path between missions in a game. Instead of laying flat in the solar ecliptic, they are all tilted in unison at some other angle, like here:

Unity transforms and Quaternion.AngleAxis were super valuable in getting this to work; the three dimensional trig I saw in research made my head spin. But that seemed to satisfy my itch for more variability, along with some price changes of materials mined from low orbit of the target asteroid, some obstacles, and other suprises along the way.

One challenge in particular (at least for my non-artistic self) was getting decent looking spaceships. I wasn't going for full blown serious production, just something that fit the theme of the game. At first I used a placeholder found from https://opengameart.org/ which is a great resource for placeholders or final art. Then I tried building one myself from blender, which looked horribly. Then I found this gem : https://www.blendswap.com/blends/view/17601 which was awesome for blender nubes like myself. I did have to learn a bunch to split the meshes apart and reduce them to reasonable densities, and then put different pieces together into 4 new ships.

The game ended up pretty large - about 140MB - more than half of which are more than a dozen 4K textures for all orbiting bodies except Earth and a handful of 8K for the Earth. I was determined to use actual asteroid meshes for all of them in the game, and a great source to play around with is https://space.frieger.com/asteroids/ Big thanks to Greg Frieger for maintaining this site. Alas, not all the asteroids I chose for the game have been visited by actual spacecraft, duh! I chose the ones that are popular, have good mining potential from another good resource https://www.asterank.com/ which lists actual asteroids, compositions, and potential mining value.

I think that about covers most of the big stuff. Challenges aplenty, but also tons of fun.