Search Unity

Comments & help on multiplayer topology/design/tools

Discussion in 'Multiplayer' started by pKallv, Jan 6, 2021.

  1. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    I know very little about online multiplay design, implementation and the tools. I once did a UNET prototype card game that actually somewhat worked, but that is all.

    I am planning for a leasure type card game where each player play independently on their device agains opponents and when local game is completed for both players result is given. This, hopefully, enable so player A can challenge player's B for a game and playing first round. Player B, if accepted, can play his/her first round days later. After both players have game over result is presented.

    I am currently researching how this can be done including matching. From a matching point of view I am thinking that player A send a direct invitation to player B via sms or social media. However, I guess there should be a general lobby as well where unknowns can challenge each other for a game.

    I have been looking for a network product to use and it looks like Mirror may be able to do that. Given the multi game mechanics maybe some sort of p-2-p file/db share design but I guess that will surface other problems & challenges like performance, consistency etc.

    I have created a topology view of how my basic thought is for the data flow.

    I would REALLY appreciate some thoughts, ideas and recommendation how to do this (low cost) and what tools I should use for a project like this.



    Network structure.jpg
     
    BetaMark likes this.
  2. BetaMark

    BetaMark

    Joined:
    Sep 27, 2014
    Posts:
    229
    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.
     
    Cranom, luke-unity and pKallv like this.
  3. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    What a great answer, thank you. I am currently finish up my current rewrite from XCODE game and will dig into this after that. Will probably need a few more details.
     
    BetaMark likes this.
  4. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    I have now spent a few hours researching your suggestions and, not unexpected, great answer.
     
    BetaMark likes this.
  5. BetaMark

    BetaMark

    Joined:
    Sep 27, 2014
    Posts:
    229
    Happy to help. Let me know if you need more input on anything.
     
    pKallv likes this.
  6. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    will do
     
    BetaMark likes this.
  7. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    A pretty old post @BetaMark but I have now finally had time to implemented REST access to an Oracle Autonomous database and it seems to work THANKS. I also use PlayFab. However, I would like to ask you for advice how to ping database for changes like a player makes a move and the other player(s) should be pinged that it is their turn. I guess some sort of server solution. I know I can use UniREST (Asset store) for this but I would like to create a server based solution.
     
  8. BetaMark

    BetaMark

    Joined:
    Sep 27, 2014
    Posts:
    229
    The way I've seen ASYNC game design work for mobile is in the past is via doing push notifications to the devices. Playfab has a nice quickstart: https://docs.microsoft.com/en-us/gaming/playfab/features/engagement/push-notifications/quickstart

    For your scenario, I think you'd need to register a push notification to "All other players" right after your REST call has successfully updated the database, but before you return your 200 OK (or whatever) when registering the move.

    If you are doing a game client that can't receive (and react to) push notifications then the lightest way is probably to have your game client side send a `GET /match/123/move_id` every 500ms where the backend returns `{ 12 }` if the match is currently on its 12th move, then you'd compare that against your in client move state and follow up to get more details through another route if, for example, you only have data for up to move_id number 11.

    Hope that helps!
     
    pKallv likes this.
  9. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Absolutely thanks.