This section of the docs covers the basics of integrating a game engine with SpatialOS.
Improbable has built game engine integrations, with source code available on GitHub, for Unreal and Unity. But if there's a different game engine you want to use in your SpatialOS project, you may be able to integrate it yourself.
At the end of the day, a worker is just a program: one that uses the SpatialOS Worker SDK to interact with a SpatialOS world. You can use many things as part of that program - including a game engine. But if you want to build a worker that uses a game engine, you may want to do more than just straightforwardly use the base SpatialOS SDK. You might want to build a integration: the workflow and tooling required to run instances of that game engine as workers connected to a SpatialOS game.
For one thing, the Worker SDK (in C#, C++ and Java) is deliberately low-level. It exposes the underlying interactions with SpatialOS in quite a minimal way. Also, your game engine may have specific, native concepts that you want to make use of. If you can map SpatialOS concepts to the concepts in your game engine (for example, the way the GDK for Unity maps SpatialOS entities to Unity GameObjects), it can make it much easier when you're writing a worker. That's why a deep integration is useful: to make SpatialOS development feel more native to those engines.
A very basic game engine integration would just connect the game engine to SpatialOS, and get it building as a worker. A more sophisticated integration might build on top of the SpatialOS Worker SDK to make development in the engine easier, finding ways to interact with a SpatialOS world that feel idiomatic for developers used to working with the engine.
Each game engine is different, sometimes with unique internal concepts. How difficult an integration will be depends on how naturally the engine's concepts map to SpatialOS concepts. But what we can tell you is:
- The requirements your engine must meet to make it possible to integrate with SpatialOS.
- The steps you'll need to complete in order to integrate the engine (though we can only tell you what those steps are, not how to do them).
Integrating a game engine can be a big task, so if you have any questions that aren't answered by this documentation, please get in touch on the forums.
In order to integrate with SpatialOS, a game engine must meet these requirements:
It needs to be written in or support C#, C++, or Java if using a Worker SDK with generated code. Otherwise, it only needs to be able to interact with a C API using the Worker SDK for C, or the Worker SDK C# bindings.
In order to run as a managed worker, it needs to be able to run:
- in Linux
- in headless (no graphics context) mode
- with root/administrator privileges
If it doesn’t meet these requirements, you’ll only be able to use it as an external worker, and you will have to use the Worker SDK in C, C++, C# or Java for the server-side.
It’s also worth noting that the Worker SDK is not thread safe. You’ll need to decide on a threading model as part of your integration.
Since game engines differ greatly, we can’t tell you exactly how to integrate your game engine with SpatialOS.
So this page just goes through the different parts of a game engine integration that are required. You’ll need to work out how best to address each point in your use case.
Bear in mind that a game engine integration can be as simple or as complex as you want it to be.
The simplest kind of game engine integration isn't any different to a straightforward worker built using the Worker SDK in C++, C# or Java. An integration built like that would use the SpatialOS Worker SDK as it is.
A more complex game engine integration would be designed to use SpatialOS in a way that feels native to the engine: mapping SpatialOS concepts to engine concepts, and making SpatialOS fit intuitively into the engine's usual workflows. You need to decide how far down that route you want to go.
You may also want to build layers for ease of use. For example, the schema-generated code for the Worker SDK in C# provides statically-typed handlers for component changes. To register callbacks when the type of component is not known statically you could use the
Dynamic feature of the Worker SDK (example from the Worker SDK in C#. You could build more generic on-component-update functions or even implement a custom View.
To begin, make sure your game engine is suitable for integration with SpatialOS by checking the Requirements.
Take a look at the Project directory structure page for an idea of how your directory structure should look. You could start from the blank projects for C# or C++: these are stripped-down SpatialOS repositories.
As per the Configuring a worker page:
- Code for workers goes in directories in the
workers/directory of a project.
- You’re not limited to one worker type per directory: if workers share code or assets, they can go in the same directory.
- Each worker needs a worker configuration file (worker.json).
Following this structure means that SpatialOS knows where your worker source is, and knows how to upload the assembly built from it. Everything else - for example, the structure inside the folder for your worker type - is up to you.
You need to work out how to integrate the SpatialOS libraries into the project build process. They can be built into the project or - if you have access to the game engine's source code - you could build them into the game engine itself.
This involves telling the build system where to look for the SpatialOS libraries, and schema-generated code. The libraries are downloaded as worker packages.
For C++, take a look at Compiling a C++ worker.
For C#, you might find the Setting up a C# worker page helpful.
For Java, you might find the Setting up a Java worker page helpful.
.zip created by your build process must be built to the directory
If you want to use the
spatial worker build command to build your worker, you need to create a
spatial.[worker-type].build.json file. See Build configuration for information on that type of file.
If you don't use the
spatial worker build to build your worker, you must make sure you run
spatial worker build build-config so that your worker configuration file (worker.json) gets built. This command will put it in the directory
You need to figure out what the flow of connecting the game engine to a running SpatialOS deployment will be.
When designing this, you need to consider that the Worker SDK in C does not offer any guarantees of thread safety. You can use a single
Connection object from different threads but not from multiple threads simultaneously, as this may result in undefined behavior.
In general we recommend pinning a given
Connection object to a single thread in as far as your engine allows. If this isn't possible, you should protect accesses to the object using a mutex in order to ensure thread safety. You can safely access different
Connection objects simultaneously as the objects do not rely on any form of dynamic global state.
SpatialOS only provides serialization/deserialization of the schema information. You may want to write a custom code generator to generate something from schema that fits more natively with the concepts in your game development engine.
Custom code generation is based on an abstract syntax tree generated from schema: see
Building a custom code generator for details.
You'll need to work out how to build on top of the View in a way that makes sense for your game engine. For example, you should decide how to represent entities locally in your game engine. It's important to correctly handle entities coming into and out of your View (as well as actually getting created and deleted).
You may want to work out how to map the concept of SpatialOS entities to a concept in your game engine, if you can do so in a way that takes advantage of the game engine's features. You could also avoid using the concept of entities, and just interact with the SpatialOS world at the component level: you need to decide what makes most sense in the context of your engine.
Updated about a year ago