Technology Stack

posted in Raiding.Zone Devlog for project Raiding.Zone
Published December 24, 2022
Advertisement
Cover

About a year and a half ago, I started my game programming journey. I am somehow confident in programming Kotlin and liked the idea of a complete game in my favorite language. My was to make a multiplayer game where you fight together to kill a boss. I played a lot of World of Warcraft in the old days, but didn’t like the amount of work I had to put in to be able to play my favorite part of the game. So to build this game, I needed technology for a game server and frontend.

My professional tech stack always evolved around Spring-Boot backend programming, and so I was very quick to chose it for this project as well. Some said it would be too bloated and slow for this purpose, but I didn’t have any problems getting the wanted performance. The server has a tickrate of 33 updates per second, and this loads just one of the 8 cpus on my machine.

I have to say I really love Kotlins Coroutines. Concurrency is hard, and concurrency that should be real time in the best case is a complete mess if you just work with threads. I know that coroutines are not real time and the delay() method provides no guarantees that it really waits the wanted amount. In Spite all this it works better than I expected as long as the whole system doesn’t have much load the Kotlin coroutine timing seems almost magical correct.

I decided to use Websockets for communication. The reasons behind this were primarily to be able to host the game server with just a http loadbalancer. My game should also be runnable in browser, to allow a quick and uncomplicated entry into the game. Later I learned that because of websockets it was much easier to port to android too. (You don’t need any elevated permissions)

Frontend was somehow a more difficult story. There is a Kotlin game engine: Korge. I have to say, it was awesome to prototype and trying out things, while I was new to game programming. The problems appear if you want to implement more sophisticated features like complex particles, z-indexing, camera or performance tuning. That, when I decided to rewrite my complete frontend in Unity to get more options and build a more compelling experience.

That created a dear problem. I had to rewrite the whole code in C# and had to find a possibility to not duplicate the multitude of data structures. I love the Kotlin annotation processor kapt and I used it extensively in other projects beforehand. At first, I only exported the raw data structures and used them in the c# code. One mayor advantage is, that if you ignore Kotlin’s nullability it is quite compatible to c#. Overtime, I also generated rest-clients and json-deserializers with the annotation processor and am really satisfied with the result. I will write another blogpost detailing the technology and code used for this.

Performance was always a main consideration of my game development journey. I aim to make my game run smoothly on any system that has 2 CPU cores. To accomplish this graphically was a fairly easy task because I don’t have any talent when it comes to digital art. The game doesn’t have any ray-tracing or overly extensive physical calculations. All the relevant heavy computation are made on the game server.

The main performance challenge was to get the gamestate to the clients. I started with whole gamestate updates and transported all data 30 times per second. But as the development processed further and the gamestate got more complex the deserialization would take 3 client cpu cores to keep up with the updates. This is definitely unacceptable because I cannot assume everyone has an 8 core system with 4ghz each core.

That’s why I moved to delta compression. I evaluated JSON delta compression, but neither Spring-Boot nor Json.Net in Unity has a sophisticated Support for this. So I chose semantic delta updates, and I would suggest it to anyone who stands to make this choice. There are per definition only a certain number of different updates a game can make. In the end I have only 11 different payloads, and they are all a lot smaller than the initial gamestate that would take up to 3mb. There is still potential if I wanted to reduce sizes further, but right now the game runs with smoothly >500fps on my machine where 60 would be enough.

0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement