Developing real-time multiplayer game using MagicOnion -2. Architectures-

System and Network architectures

Table of Contents


This is second tech post about my game development. In this post, I’ll show you my game’s system or network architectures.

You can see other posts or source code are as below.

  1. Developing real-time multiplayer game using MagicOnion -1. Overview-
  2. Developing real-time multiplayer game using MagicOnion -2. Architectures-
  3. Developing real-time multiplayer game using MagicOnion -3. Client Program-
  4. Developing real-time multiplayer game using MagicOnion -4. Server Program-
  5. Github Source Code / LineDeleteGame

System Archtecture

The system architecure of my game development is as below image. Let’s see each domains.

Client domain

Client domain behaves as browser just draw information which is received from server. I’ve used Unity to send user inputs to server, draw blocks, play effects, and transit game scene.

MagicOnion is used for communicating with server. MagicOnion is a RPC framework for .Net. It is enable for us to describe unary or bi-directional real-time communications using C#. Thanks to MagicOnion, we can write C# source code between client and server consistently.

In this chance, I have adopted UniTask to learn asynchronous programming. UniTask is an asynchronous library which is tuned for Unity.

When we develop game program in an environment using garbage collections such as Unity or C#, we have to avoid “GC Alloc”. C# try to garbage collect to allocate memories when the spaces don’t have any empty spaces. We will face “Stop the world” effect in our game playing because it is very heavy execution. For example, it is very disappoint for us to see that the fighting game’s combos are interrupted by “Stop the world” effect. To avoid this, game programmers try to allocate all objects before game beginning, and try not to allocate anything while players are playing game.

Although game programmers pour one’s heart and soul into avoid new allocate, system libraries may call allocate executions in their inner process. “Task”, a C# asynchronous system also call GC Alloc execution inner it.

We can avoid it to use UniTask which is tuned for Unity asynchronous. In this experiment, I’ve used it various places for learning.

Server domain

I’ve used C# and .Net Core for server hosting. .Net Core is an open source and cross platform C# framework. It is used for developing console app and web server hosting services and it is enable for us to execute anywhere. Though I’ve developed my server program on Windows first, it have been able to deploy anywhere such as Mac or Linux. MagicOnion assumed for using on .Net Core, so we can introduce it easily.

The worthy of special mention in my server program is that I’ve adopted LogicLooper . If we describe main game logic in server, we have to execute game loop in it. But this is my first server program experiment, so I don’t know anything about how to, or where to describe it. In order to achieve this, I’ve googled very much and finally I’ve found LogicLooper that it can describe server loop using threads. I’ve decided to adopt it because the sample of this library can be modified to my server logic. Though I don’t have enough knowledge about threads, I could achieve my objective.

Shared domain

I’ve described previous post, my game support offline game playing. So the pure logic of game must deploy to shared place and be referenced between client and server domain. When we can achieve it, we mustn’t describe domain dependency execution between them. For example, Unity’s uGUI logic mustn’t be described to shared domain. If they are mixed in shared domain, you are wrong because you have failed to isolate game logic and view.

In my program, I described just pure C# logic which is not dependent Unity or interface there. MagicOnion’s rpc interfaces are also desctribed there, too.

Network Architecture

The image of network architectures of my server program is as below. We can divide them to main two streams, matching server or main game loop server. All of them are communicated with MagicOnion’s gRPC.

Although each servers are received their requests on the same server directly, we have to consider more deeply for scale out if we deploy it to public server. For example, we can have proxy server or load balancer internal client and server, and they will distribute client’s requests to each servers.

If you wish implementing any score ranking systems, you can place database servers back of them.

Matching Server

Clients send matching requests to “Matching server” to search their opponents. In this experiment, I’ve implement very simple way that player will match first come. If you want to implement richer matching system such as based on user’s score, you should have database servers.

Main Game Loop Server

When the matchings are succeeded, clients request game starting to main game loop server based on the matching information. Main game loop server confirm that preparing are finished, it responses them that they can start playing game.

This server calculates board’s information and scores every frames, and sends to clients its results on real-time during the sessions are established. Clients receive its results and draw them to display. They just send continuously their key inputs and they can’t interference board’s informations without inputs.

Next Post

In this post, I’ve shown you my game’s system or network architectures. Next post, I’ll show you that how I’ve implemented client program in my game development.

Game Programmer
Build Engineer

I’m a Game Programmer. In my work, I often use Unity3D Engine with C#/C++ to develop game app.