A couple months ago, I started experimenting with network multiplayer games in the Godot game engine. First, with Battle Pong, which was just to learn the basics of the Godot High-level Multiplayer API. And then, with Retro Tank Party, which was to try and make an actually fun network game.
When the tank game started to be kind of actually fun, I wanted to take the multiplayer to the next level...
This meant I needed to have some persistent server component!
But, I didn't want to have to build that custom... I want to focus on making my game AWESOME!
An Open Source game server that I can just drop in and use without writing my own? Perfect!
I ended up integrating it into Retro Tank Party, and it's now providing user authentication, matchmaking and part of the multiplayer setup for the game. You can read more about how that game is using it in a separate article.
I also created my own client library for interacting with Nakama in GDScript, which is what this article is about. :-)
If you want to learn why I made my own library, and how to use it - read on!
What can Nakama do?
Nakama has a ton of really interesting features:
- Authentication via several services, including Google, Facebook, Steam, etc
- Friends, Groups and Clans
- In-app notifications
- Leaderboards and tournaments
- Realtime chat
- Realtime multiplayer
- ... and more!
It's also possible to extend the server with custom functionality written in Lua. So, if you need to enforce certain rules in multiplayer, or have a complex multi-tiered tournament, you can write a little module in Lua to handle that.
Honestly, if I had created a custom server (instead of using Nakama), I would have just done the bare minimum. But since Nakama already supports all this cool stuff, I'm dreaming up exciting ways I can have my game take advantage of it. :-)
Why create a new Nakama client library?
There's a couple of existing libraries for Godot out there, but the community ones I looked at were pretty incomplete (only covering a tiny bit of the API), or had some unusual limitations (like, only allowing a single request at a time). I don't think I saw one that addressed the realtime API at all.
Nakama itself provides several client libraries, including a C# library that supposedly works with Godot. I tried it, and couldn't work around some .NET compatibility issue (the library wanted net46 but Godot uses net45). But I also ultimately wanted to make an HTML5 game, and Godot can't export C# to the web (yet).
I also tried making a Godot module in C++ using Nakama's C++ client library, but encountered issues with compiling the dependencies of Nakama's library. I spent a bunch of time on that, and probably could have worked it out, but ultimately it seemed silly to need all these dependencies for handling HTTP requests and WebSockets, when Godot already has code for doing those things right in it.
So, I decided to use the functionality built into Godot to make a client library in GDScript, which would work on any of the platforms that Godot supports. Since I'd be building it from scratch, I could also make it more Godot-ish and so hopefully easier for Godot folks to use.
How does it work?
It's provided as a Godot addon, that you can copy into your project. Hopefully it'll be available in Godot Asset Library soon (it's awaiting approval).
Once enabled, you'll be able to add a "NakamaRestClient" node to your scene, configure it for your Nakama server, and then interact with it from any other script on that scene.
I used the Swagger definition of the REST API to generate methods for the complete API, although, at this point, most haven't actually been tested. :-) Once you're authenticated via the REST API, you can create a realtime client for interacting with Nakama's realtime (WebSocket) API which is also completely supported.
It makes copious use of signals, which hopefully makes working with it very familiar to Godot users. You can also choose to interact with it via promises, so that you can easily use the same client node to do lots of different things. And combining promises with coroutines (GDScript's "yield()"), you can pretty naturally write code that feels synchronous, even though all calls to Nakama will actually be done asynchronously.
See the project README.md for more details on exactly how to work with it, including some code samples.
I still think it'd be worthwhile to make a Nakama client library as a Godot module in C++.
First of all, it could potentially be faster because it could use gRPC rather than REST. And, of course, as Godot module, it could be compiled for all the platforms that Godot supports.
But most interestingly, you could allow Godot's High-level Multiplayer API to use the Nakama Multiplayer API as a backend. This would allow games that are using Nakama to very simply become multiplayer games. (In my tank game, I'm just using the Nakama Multiplayer API to negotiate WebRTC connections that are used for Godot's Multiplayer, but I think there is a use-case for using Nakama's Multiplayer API directly.)
Anyway, I don't know if or when I'll ever work on that, but I think it would be really good for the Godot game development community.
Contribute, test and send me your thoughts!
The Nakama client is Open Source, under the MIT license, and hosted on GitLab:
Check it out! If you find any issues please create an issue or merge request.
I look forward to hearing what you think. :-)