I want to start with saying that this is one of the best “I would like some feedback” post I’ve seen. Thank you for thoroughly thinking through your design and asking the question from a place of having thought it through already.
Now, for an async game loop that could last days, I would not recommend any of the traditional “multiplayer” solutions that you’ll see recommended for Unity games. At least from the ones that I’ve got a tiny bit of experience with (unet, photon pun, smartfox, and mirror), they all assume that each “match” is stateful, sustained in a “room” of some sort, kept in memory, and kept in sync with all of the clients in near real time.
You don’t need any of that extra complexity for this kind of game, and it will also drive up your server costs with little gain in value for the players of your game.
What I’d recommend instead is to build a REST backend with any of the good web/api backend frameworks out there (or design your own with something locode/nocode like WayScript) – and to do all of your server things via stateless async requests to a web api.
The immediate benefits:
- login via facebook, google, twitter, instagram, discord, perhaps even steam etc. Anyone who provides federated http login is going to work here
- your “server” will be able to handle hundreds, maybe even thousands of simultaneously running matches, even if when are running on a really lightweight free instances on a cloud provider like AWS.
- web servers, REST api design, and good SQL or noSQL database design solutions are plentiful, and there are lots of people (myself included) that do work with those kinds of things at their day jobs and could help you out.
- All of your state would be kept in a database, synced to disk, easy to report on for leaderboards and cheat detection and easy to backup regularly.
- monitoring tools for everything from basic server performance to tracking the performance of individual request are available for all of the popular web api frameworks, giving you peace of mind that your game server is up 24/7, and you know if anything is slowing down or seeing errors immediately.
Now, if you and I were at a hackathon and you tasked me with building this in the next 48hrs, this is what I’d use to build it:
- Postman to design, document, communicate with you about, and actively test and monitor the API
- I’d design a REST API over HTTPs
- I’d use Python with Flask and Nginx as they are a very common, lightweight, and easy to get help with.
- I’d use the Unity asset called “Best HTTP/2” for the game client to handle all the http requests (its still on sell 50% off, btw), as it is designed for exactly this scenario
- I’d use a single AWS ec2 free tier server for the web front end, running behind a load balancer with https for security end to end
- I’d use a free tier RDS instance for a SQL server (probably Postgres)
Then I’d sit down with you and look at the data that needs to be structured, normalize that into SQL tables, and then I’d build all the API endpoints for all the client-to-server conversations.
The result is that you’d end up with some really strait forward REST endpoints that would look like the following (based on your diagram above):
User:
POST /api/v1/user/register
POST /api/v1/user/login
POST /api/v1/user/forgotpassword
GET /api/v1/user
UPDATE /api/v1/user
Match:
GET /api/v1/matches
- gets a list of all currently registered matches with some details on the user in those matches
POST /api/v1/match/register
- register a new match
POST /api/v1/match/join
- join a match by ID, potentially with password
POST /api/v1/match/match_id/make_move
- All of the server authoritative game logic would happen during the make_move post for the match.
- This is where all the logic for “can the player legally make this move” and “what does this move do to the game state” will be handled.
- I’m a little fuzzy on this one, as I don’t know exactly what goes on in the player’s move, but it would probably follow this kind of mechanism
- unless moves are much more nuanced, and then I’d make a whole separate area of the API for just moves, and we’d just pass those requests the match_id to link to this match
Leaderboard:
GET /api/v1/leaderboards
- list all leaderboards and their basic metrics, perhaps with a filter applied
GET /api/v1/leaderboard/match_id
- get details on a particular match
NOTE: all the leaderboard stuff would be derived from match data, so nothing for users to register at the end of the match.
If you’d like more details on how I’d set this up for a quick POC, just let me know.