What game engines can't do - Writting robust netcode


Why make your own engine when you could've used unity, godot or unreal?

It's a question I get pretty much every time I talk about etetgame and for good reasons. Modern game engines are very capable pieces of software, so why do all the legwork by making your own?

Superiority complex

If you go on Youtube you find countless videos of developers jumping through comedic amount of hoops by making everything from scratch to get some really simple game made for the sake of entertainment and content. There's a myth of a legendary programmer making everything from scratch and riding their waves of ego. I won't deny that it's a great thing to do for educational or entertainment purposes and something I've done plenty of times when it comes it realities of gamedev. Nothing reigns more true than the old saying of "an idiot  appreciates complexity,  a genius appreciates simplicity". As I gained more and more experience and participated in game jams I found myself to be genuinely impressed not by someone making something from scratch but by someone utilising engine tools to make something fun and playable in minimal amount of time and effort.

 Yet I still made etetgame with a custom engine, why?

Unity

At first I set out making the game in Unity. Unity has a great selections of premade components that work freeform 2d and 3d games - however etetgame structurally is based around an isometric grid so I ended up constantly converting 3 coordinate systems of world coordinates, grid coordinates, grid pixel coordinates and at a certain point I realised that since I'm doing everything on this grid coordinate system I was gonna need to build my own ray casting, collisions detection, pathfinding, field of view and plenty of other mechanics from scratch so in a way I was almost gonna build an engine on top of an engine.

That combined with the fact that Unity's support of networking is quite lacking. Most common networking solutions are pretty high level and boil down to adding "sync" components to game objects that synchronise their attributes across clients. This is great for goofy 3d physics games that Unity tends to produce as well as any other Realtime genres. But in case of strictly hardcore, deterministic games like etetgame it's just adds more issues than it solves and leads to jankiness.

Inspiration


Quite some time ago I made mods for a game "Barotrauma". At first by decompiling the game and later by using the released source code(I am now in the community section of the credits :3). Despite Barotrauma being completely different genre and type of game to etetgame it served as a big point of inspiration for a lot of techincal thigns. The "Three Project Structure", XML encoded prefabs and general appraoch to community fostering were inspired by what Baortrauma did.


Three Project Structure

The games code is divided between 3 directories, Client Source, Shared Source and Server Source.

Client and server source folders are pretty intuitive. Client contains a lot of stuff related to rendering, ui, and menus while server is pretty small containing server side game logic and some general client management stuff like chat and keeping track of last seen positions.

However the magic bit is the Shared Source. It is compiled for both server and client Generally what ends up happening is that the client runs checks to verify that an action is doable client side and communicates that through UI and if everything is OK it sends it to the server. If someone is used a hacked client they can send fake inputs that should be illegal which is why the server runs Identical code to verify if the actions are legit.

Traditionally, client and servers are written separately which is not only double the work but also leads to mistakes. The root cause of flyhacks and speedhacks in videogames, is that the client code is correct and prevents people from doing ridiculous things. However the server checks were not implemented properly and because of that a hacked client can send illegal inputs.

Preprocessor Directives


The final piece of the puzzle is pre-processor directives. When compiling code in c# you can use pre-processor directives to only include certain bits of code. The code above is from the shared source directory, it's the code for unit executing an action. At first the client runs this code, does all the game logic to verify an actions is OK but at the end instead of doing the action it communicates it to the server at which point the server runs almost the same code but at the end it actually performs the action and communicates the results to the clients.

Flyhacks, speedhacks and any other type of illegal input hacks are impossible by design: the same code that runs to grey out buttons for client ui is the same code that runs on the server to verify the actions.


Replicating this kind of structure is impossible in unity. Newer versions of godot and unreal are somewhat more alike to this but they still have the isometric grid problem and a few other quirks beyond the scope of this blogpost.


-Etet

Get Etetgame

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.