Stop me if you’ve heard this one before: Developer wants to create a space combat game in a procedurally generated universe and has lofty ambitions with poor scope-management skills.

No… I’m not talking about Chris Roberts or Sean Murray in this article.

# I’ve always wanted to create a space combat game

It started when I was boy, sitting on the couch watching Star Wars with my dad for the very first time. It would only continue to grow as I played games like Wing Commander, Rogue Squadron, Star Fox, and Freelancer. This even led me to attempting my own VR flight simulator in the past, which was a very messy failure.

Now it’s 2016, I was playing a lot of Elite Dangerous and was eagerly anticipating the release of Star Citizen, which was due to come out any day now. Unfortunately, these games were too focused on realism and simulation to satisfy my desire for something more fast-paced1.

While shuttling cargo from one station to another in Elite Dangerous, I started making notes but what I wanted to be doing instead. I went back and watched various scenes from Star Wars or Battlestar Galactica, only to lose an internal argument about what I should do with my time.

# The project begins anew

During the day, I was working on a client project in Unity through Helpful Human. Unity is a technology I had experience with throughout the years as I continued to dabble with game development and C#, so it was the first choice for this project.

However, I would later move the project to Unreal Engine 4 after I heard that it was available to indie developers for $20 a month. This is why you’ll see a mix of media from both engines throughout this article.

The initial vision of the game looked something like this:

  • Fast-paced space combat with a focus on dogfighting.
  • Procedurally generated universe with different celestial bodies and color palettes2.
  • Networked multiplayer to allow for cooperative and competitive play.
  • Customizable ships that allowed hard-points to be changed out.
  • Player-driven factions that would vie for control of territory and resources via “longplay 4x-lite mechanics” and missions.
  • Dynamic PvE director that would create missions and encounters based on player performance.

# Trying to nail down a flight model

I started by creating a simple ship model and experimented with different approaches to ship movement. I couldn’t decide between first-person or third-person perspectives, so I tried to implement both.

My very first attempt at a flight model, complete with boost.
My next attempt, this time in Unreal Engine. The lines being drawn show where the auto-locking weapons are tracking.

This turned out to be the first of many lessons learned on this project. I found that these two perspectives do much better with different control schemes.

The first-person perspective naturally inclined towards “realistic” flight controls. Where Newtonian physics are in play and your input is a suggestion to where you want to go. This is an approach I felt I wanted, because it was more immersive and would allow for more interesting maneuvers like “sliding”3. This approach led me to learning all about PID controllers in order to achieve the feel I wanted.

The third-person perspective was more arcade-like. It was more about “pointing” your ship in the direction you wanted to go and flying by wire. This was more accessible and easier to control, but it felt less immersive and far more arcade-like.

I tried to find a hybrid approach I felt happy with, but I never did. If I was to do it again, I would have picked one and stuck with it — likey the first-person perspective as it offers more depth and expression in the flight model.

The hybrid flight model in action.

# Generating a “universe” of content

The next stage was to create a universe for the player to fly around in. There were a number of lessons learned from this process. Floating point precision was a big one, along with view frustrum clipping planes. These 2 issues slapped me right in the face as I attempted to create a solar system with a sun and planets.

This meant I needed a solution to either “look up” prepared information about a solar system or generate it on the fly. Procedural generation was something I had been introduced to only years before thanks to MineCraft and quickly became the solution to this problem.

My procedural generation system, like most, was based on a pseudo-random number generator that would take in a “seed” and output a deterministic result4. This seed was a 32-bit integer that would then operate as an ID for each solar system in the game.

The generation of each solar system focused on things that players could never alter, allowing the content to remain consistent for the lifetime of the game5. This included:

  1. The type, size, and color of the star at the center of the solar system.
  2. The number of planets and details about each planet.
  3. Other celestial bodies like moons and asteroid fields.
  4. A time-table for the solar system that mapped the positions of the planets and moons relative to the sun using the current time of day of the player’s machine.

# Stepping through the layers of scale

Now I had another problem: When we’re flying around in ships, we’re going to be somewhere within the solar system. Once we create a solar system, we need a way to place areas and objects within it that can also generate their own content.

The solution was a second 32-bit value representing two 16-bit components:

  • The first 16-bits would represent the rotation relative to the sun. Due to the maximum value of an unsigned short being 65,535, this meant we could only represent a precision of ~0.00549316406 degrees.
  • The second 16-bits would represent the distance from the sun. Each unit represented an “arena” of playable space that was equal to the size of a cubic 32-bit float6. The unsigned short represented a value starting 5,000,000 kilometers away from the sun7.

Great. With this solution in hand we can generate and cache information about the solar system on the local machine. This is important for handling the rendering of the sun and atomsphere in the skybox, as well as the positions of the planets and moons using “Earth” “time against the time-table.

If we want to fly to a specific spot within the solar system, we simply find where it is in relation to the sun and create the seed. While “dropping out of warp” into the space, we generate the content locally for the area and fetch any dynamic content from the persistent server.

# Oh right, we gotta talk about the “persistent server”

I had a vision of a game where players could exist and make persistent changes in shared universe. Rather than having a single game server that tracked this data, I decided to offload this responsibility to a MongoDB-backed web service.

This service would track actions taken by players and store them in a database. This included the obvious things like information about players, factions, and the various space stations in each solar system. Less obvious was a set of CRON jobs that would generate new content (missions) and perform background simulations to make the universe feel “alive”.

The plan here was that players could use a web client to check on the status of their faction and take part in the strategy element of the game. This aspect of the game was less fleshed out than the hands-on portion, but it was a key part of the vision initially8.

Game clients would call into this service to fetch information when needed and were allowed to send specific updates based on what the server knew about the player’s location and active mission.

# Rendering big things with small values

This was a problem that took me a while to figure out. If I’m in space battle above a planet (a’la the Battle Above Coruscant), how do I render the planet in the background?

The solution was a classic trick used by various games 3D backdrops and skyboxes. Make a small version of the planet (and other celestial bodies) and render it on one layer, then render the actual game on another layer and don’t clear the buffer.

Tip

It’s effectively the inverse to how a lot of first-person shooters render their gun models, where the game world is rendered and the gun is rendered on top of it. This prevents the gun from clipping through walls and other objects. We kind of did this with a third layer for the ship’s cockpit and HUD.

The first layer with the backdrop elements should have a camera whose rotation matches the main gameplay camera, but not the position. This is because far away objects move slower than close one, so huge objects should barely move at all.

When the project was moved from Unity to Unreal, I had to find a different way to implement this system. Unreal’s rendering pipeline is very different from Unity’s, so a custom material using techniques like panini projection was used to achieve the same effect.

This shows how procedural generation integrates with the skybox.

# So much to model… I need help

With the untamed scope of the project and my limited time to work on it, I knew I would need help. While talking with a friend, he mentioned that a mutual acquaintance of ours might be interested in a project like this.

That mutual acquaintance was Dan Taylor. We’d known each other from a school group from a decade prior and were in a lot of shared friend groups. We got to talking and he wound up collaborating on the project with me.

Dan is a very talented artist and had previously wrapped up school for industrial design. While working on the project, he created a number of models and even a custom font for the game.

Font created by Dan Taylor
CtH Mono: Created by Dan Taylor. This guy’s skills seem limitless.

Though we would never finish this project, Dan and I became close friends through this process and would go on to work on other projects together. Some of these were Out of Control Center, BullShoppe, and The Grind.

Dan then introduced me to someone he knew from college, a talented artist named Tyler Mead. Tyler would eventually help out with some ship concept art and 3D models.

# The project stalls

Development on the project continued for a few years, often in short bursts of focused time investment. But it was always in the background as a side project to several other efforts demanding my attention. Other ideas for projects would capture our interest and the shear scale of the project would see it put on hold indefinitely.

Maybe one day, with the right team, time, and budget I’ll revisit the idea; likely with an altered vision and definitely a smaller scope.


  1. I love Elite Dangerous, but it’s definitely not a “fast-paced” game. There’s a reason videos like this exist↩︎

  2. This was all before I knew about No Man’s Sky↩︎

  3. “Sliding” was inspired by a maneuver seen in the Battlestar Galactica reboot. It involves shutting off your primary engines and flipping around to fire at a pursuing enemy. ↩︎

  4. Determinism means that if you give the same input, you’ll get the same output. So the equation of 5 + 5 will always equal 10↩︎

  5. Opposed to the dynamic content of the game, like space stations which could be destroyed or moved. This content would need to be stored and managed separately. ↩︎

  6. With each unit of the float representing a meter. This means the the size of each playable area was roughly ~4,294,967 kilometers. ↩︎

  7. This decision was made because that’s roughly how far you’d need to be from the sun to not be vaporized instaneously. ↩︎

  8. It’s the reason for the “Conquer” part of the game’s title. ↩︎