One of our programmers used Unity and SpatialOS to prototype an online multiplayer game where adventurers fight spiders for control of the world. By the end of her two week sprint, the game supported three different kinds of gameplay (adventurer, storyteller, dev), and it was tested with a thousand simultaneous AI-controlled players.
This article shows how she did it and highlights the most relevant parts of her source code.
Abyssals is set in a world where players must fight against the darkness to survive. The art style is very Dark Souls-esque, because Improbable’s artists love a badass sword.
Light plays a large role in the game mechanics. It allows adventurers to see their surroundings to explore and find treasures. At the centre of the world it is safe and light. At the edges it is pitch black. It is a constant battle between the adventurers pushing light outwards, and the creatures of the darkness pushing back.
Abyssals is built on SpatialOS, using Unity for the game clients and for physics simulation.
Everything in the world is an entity. This includes adventurers, spiders, equipment, and environment objects. Entities are made of components, which define different facets of what an entity is, and behaviours, which describe how these components change as the entities interact with each other.
Components and behaviours can be reused by many different entity types. For example, the spider and the adventurer share almost all of their code; the torch and the bonfire share almost all of theirs (except a bonfire can’t be put in a player’s inventory). This cuts down on code, which is especially useful when you only have a single game programmer!
These components are independent from each other, so they can be combined in interesting ways. For example, both adventurers and spiders use the Health component, but spiders don’t have the Armor component. They are terrifying enough without extra protection!
The component definitions are here.
Behaviours are pieces of code that determine how the entities, well, behave. This can be anything from spider AI to the logic of dying when health reaches zero; that is, anything you would call “game logic”.
In Abyssals, both the spider and the adventurer use the Attackee component. The associated AttackerBehaviour lets an entity receive commands to attack and send damage to another entity. The AttackedBehaviour entity will receive damage messages and change its health accordingly. In fact, the spider and player share almost the exact same code. The only difference is that the spider has an AI controlling it, and it can detect light sources.
At one point a dead spider body was following me around, which was super creepy. The bug was that the AI wasn’t listening for isDead to change.
The game logic is here.
The client is built on Unity. Most of the client code deals with visualising the simulation; for example, turning lights on and off, smoothly changing the size of things, drawing health bars, controlling the camera, and so on. The client also reads player inputs and sends them back to the simulation.
The client code is here.
Players aren’t special in any way; they are entities, just like the spiders and the torches. The only difference is that they get commands from a game client, and the spiders get them from an AI behaviour. Making a game this way means it can be multiplayer by default.
There can be thousands of players and spiders in the world, but SpatialOS sends each client updates only for the entities that the player can see, and only the components relevant to the visualisation. For example, the client gets the position and rotation of the spiders, but not their AI state, since that is used by the AI code that runs in a logic worker in the simulation layer.
All of this happens behind the scenes. There is no networking code in Abyssals; it was essentially coded as a single player game on my own machine, and then deployed to the cloud, making it instantly playable for anyone on the Internet.
Once the game is running in the cloud, you can use the SpatialOS web interface to look after it. You have logs, monitoring dashboards and alerts to make sure it is healthy. You can use the world viewer to inspect the internal state of the game world:
In order to see how many players you can connect at the same time, just create a bot client which connects to the game just like the Unity clients do.
We ran a thousand of them:
This worked just fine, and it required no optimization work on our part. These aren’t bots running on the simulation, but actual clients that connect and use a simple AI to generate player inputs, instead of reading them from a real mouse and keyboard.
A thousand players running around killing giant spiders is fun, but we wanted to add more ways to interact with the world of Abyssals:
They are similar to the storyteller in a tabletop RPG. Each of these is just a different view into the game world, with different visualisation and controls.
Adding a spectator player would be as simple as cloning the Unity scene, changing the camera controls, and having the client visualiser spawn a non-physical prefab in the world. This game client could run on PC, mobile, console, or even use a VR headset.
The dev is another game client type, that only very trusted people are given access to. In the dev view, the player can change the attributes of game entities in real time. For example, they can make a single spider gigantic and powerful!
The dev can also see all the currently logged-in players including adventurers, storytellers, and other devs. The dev is all-powerful.
The storyteller has the ability to shape the adventurers’ world around them on the fly. They are a game master, but with limitations. They work within the rules of the game, so the players have a fighting chance against them. Think something like Dungeon Keeper or Evil Genius). It’s their job to make the game as fun as possible by injecting a human element in addition to the AI.
If the storyteller wants to create 200 spiders around a player, they can. SpatialOS will automatically spin up new physics and AI workers to handle higher load—-this is invisible to the game developer and the players, and has no impact on game performance.
In this simple prototype the storyteller can only create and modify spiders. However, the system has been designed to be easily extendable with new content, so giving storytellers the ability to create quests or mess with players in other ways would take just a few more days of coding.
Couple the power of SpatialOS with a dedicated team of designers and artists, and suddenly you’ve got the groundwork for a massive, multi-client, production-ready online game that supports thousands of simultaneous players, in a matter of weeks.