Appearance
Appearance
The Metaplay SDK’s game server uses a stateful, actor-based architecture built on Akka.NET. Actor systems are distributed by design and achieve very high resource efficiency and low latencies. They are a great match for the typical workloads of F2P games and easy to run both locally during development and in a large production cluster.
The game server is fully programmable with source code included in the SDK, allowing you to customize the existing behavior, implement completely new game features and mechanics, or even completely new genres. Metaplay is great for extending existing genres with new types of player interactions and for making games nobody has done before!
💡 Pro tip
The game server is a C# project and only requires the .NET SDK as a dependency. Running both the server and the Unity editor on your local machine makes the development cycle very fast and allows you to use the full power of Visual Studio to breakpoint and inspect your server code right on the development machine.
In the Metaplay SDK, the core game logic is based on a server-authoritative command-pattern model where the game state is kept on both the client and the server, and all player Actions are executed on both sides. As the game logic gets executed deterministically and produces identical results on both sides, the amount of client-server traffic can be kept to a minimum while validating all Actions performed by the client. Server validation makes the game economy cheat-proof against conventional client hacks.
The game logic code is written in C# and then shared between the client and the server by compiling the same code into both of them. Code sharing makes development incredibly fast and eliminates a whole category of common bugs as there’s no need to implement the server-side logic separately in another language. For more information on the synchronized execution model, have a look at Deep Dive: Game Logic Execution Model.
💡 Pro tip
The Metaplay SDK also supports an offline mode where a simple mock server is embedded into the Unity game client, requiring no running game server at all. The offline mode emulates enough of the game server to allow game client programmers, artists, game designers, etc. to work without connecting to any server!
Entities are the backbone of games built on Metaplay and represent most of the things in a game: players, guilds, sessions, battles, etc. On the server, an active Entity is backed by an Akka.NET actor. The Entities can implement custom logic, communicate with other Entities using message passing, and contain state synchronized with the client using Models and Actions.
Entities communicate with each other via message passing with very low latencies. Any Entity in the game can send a message to any other Entity, which offers a great deal of flexibility for implementing social and multiplayer game features. See Deep Dive: Entity-to-Entity Communication for more details.
Keeping the active Entities as actors in the server’s memory makes operations very efficient as they do not need to access the database. The frequency of player actions generally only has a small impact on the overall server performance. When an Entity is no longer active, it is hibernated by persisting in the database, and then all the runtime resources, such as the actor, are released.
The Metaplay SDK has built-in support for developing data-driven games through its game configs system. By implementing your game’s key balancing in data you unlock powerful workflows like over-the-air updates without client patches and the possibility to use external editors to manage your data.
A typical workflow is for the game designers to work in spreadsheets to generate the game’s economic data. The resulting files (often CSV or JSON) are then processed using Metaplay SDK’s fully programmable build pipeline, which produces a highly efficient binary-formatted archive. These archives are highly portable and can be either tested locally or uploaded to a game server for publishing. Published config archives get distributed to the game clients via a CDN without the need for separate client updates.
The whole game configs pipeline is fully programmable. You can implement support for custom data sources, formats and even perform advanced transformations of the data as it is being processed into archives. The game configs system also has built-in support for specifying alternative values (often called “variants”) for a single data point to make A/B testing possible.
For more details, take a look at Working with Game Config Data.
The Metaplay SDK’s software architecture is distributed by design to support the volumes and workloads of hundreds of millions of players that typically will be much more than any single machine can handle alone.
In a cloud deployment, the game server is deployed into a Kubernetes cluster of virtual machines. The Entities and Actors get distributed across Kubernetes pods and they use message passing to keep the whole cluster functioning like a single, tightly connected game world. The end result is, that you can confidently develop the core game logic on top of the Metaplay SDK’s distributed model and tune the clustering performance separately based on your game’s needs.
For a dedicated overview the cloud infrastructure, check out Introduction to Metaplay’s Cloud Infrastructure.
The game server hosts an ASP.NET web server that exposes a secure administration REST API. The Metaplay SDK’s built-in LiveOps Dashboard uses this API to manage the game server remotely. You can extend the API to provide game-specific functionality, integrate with external services or even provide a public API for your players to consume on their community sites!
For a hands-on guide to the REST API, have a look at Working with the LiveOps Dashboard HTTP API.
The architecture choices make Metaplay extremely efficient in terms of compute and memory resources. Typical Metaplay-based games can run approximately 1000 concurrent players on a single AWS vCPU.
💰 Let’s do the math
A game with one million DAU should expect to have around 50k concurrent players, requiring approximately 100 vCPU to run with plenty of headroom for growth and sudden activity spikes. The monthly cost for such a setup, factoring in all the other resources, is in the ballpark of $4000. For reference, a game with 1M DAU should be grossing multiple millions, if not tens of millions, of dollars per month.
Metaplay’s cloud infrastructure enables the distribution of the entire Entity workload onto multiple Kubernetes pods which are distributed over multiple EC2 instances. Metaplay allows flexible configuration of which Entities should be running on which pods. Metaplay natively supports horizontal scaling by deploying multiple copies of each pod type. As Entities use message passing for communication, they can be freely scheduled across the cluster while still forming a single fully-connected world.
A typical example of workload optimization is to have multiple nodes for the large number of player Entities that cause most of the load. Supporting services, like the guild recommender, that do not need multiple copies of themselves can run on a single shared node. Distributing Entities to specific nodes allows for the underlying virtual machines to be further optimized for their unique workloads!
The main connection to the server is a persistent TCP connection. The two-way communication between the client and the server is low latency and supports real-time multiplayer gaming. The connections are secured with TLS.
In a cloud deployment, the client connections first get handled by load balancers that terminate the TLS and route the traffic to a game server node that has free capacity. From there, the connection is further routed to the node running the player’s Entity.
An Entity’s persisted data can only be modified by the Entity actor itself — it is never directly modified in the database. This means that for any messages to be handled or Actions to be triggered, the entity is first woken up into memory, thus guaranteeing that the now-running actor is always in the latest available version. Have a look at Entity Schema Versions and Migrations for a deeper dive into Entity migrations.
During an active session, it is possible for something (a bug in the game code, a fault in the underlying VM, etc.) to cause the actor to crash, causing all unsaved game progress to be lost. The Metaplay SDK mitigates this risk by serializing the Entity back into the database periodically during the session and immediately after important Actions like in-app purchases.
At times in your game’s life cycle, you may want to batch jobs to guarantee that all Entities of a type have been woken up at least once to migrate them to the latest version. We have built easy-to-use tools for such maintenance operations. Have a look at Database Scan Jobs for an overview!
✅ Good to know
The Entity is the unit of distribution in a Metaplay cluster. This means that any operations within a single Entity are effectively atomic — there’s no need to worry about the operations being only partially applied. But when multiple Entities interact with each other, the Entities may end up on different physical machines and have a network connection in between, thus requiring synchronization for transactional operation.
The Metaplay SDK uses its own custom binary format for all client-server communication and database serialization.
The format is similar to Google's ProtoBuf, but has the following benefits over standard solutions:
PlayerModel
are persisted in the database as it is sent to the client. The serializer can be controlled with attributes.See Deep Dive: Data Serialization to learn more.
The game server gets its environment and deployment-specific configuration from the Metaplay SDK’s runtime options system. The system allows you to selectively and flexibly override existing server configuration and extend it with your own game-specific options.
Have a look at Working with Runtime Options for a hands-on guide.