Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Help with multiplayer turn based combat using PUN

Discussion in 'Scripting' started by RavenOfCode, Feb 19, 2016.

  1. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Over the last two days I wanted to see if I could make a simple multiplayer turn based game using PUN. I got the basic stuff as far as units working (moving, fighting, stats, ect.) but I seem to be stuck on getting the turn based part working correctly. Could anyone give me some basic tips on how to structure the turn based part?

    I am currently using an array for players that is synced on all clients, then when a player finishes their turn the next player in the array goes (or it cycles back to the first player if the last player went). If it is your turn you may move one of your units (a bit more complicated for what units you can use but I dont need to get into that). Then after your turn the next player in the array goes.

    I'm not sure if this is the best way of going about things, does anyone know of a better way?

    Any help is greatly appreciated. :)
     
  2. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    When you mentioned:
    is it array of PhotonPlayers or your PlayerScript that handles player logic? In case you are using PhotonPlayers, I would personally revise that, because turn based games are often asynchronous, meaning one player could close application while waiting for his turn. Or even get disconnected for any reason.

    Using an array to check which PlayerScript is currently active seems ok, but I would not sync them in real time. Rather, I would pass an EndTurn message so that all players update the new active player manually, meaning each player simulates the game on its own. That way you can recreate your steps when you accidentally get dc or enter the game when you received the notification for your turn.

    You don't even need to hold all messages, you can use PhotonTarget.AllBuffered:
    Code (CSharp):
    1. JSONObject message = ...
    2. photonView.RPC("EnqueueMessage", PhotonTargets.AllBuffered, message.ToString());
    and any player that joins the room, loads your battle scene can easily fast-forward the simulation because he will receive all messages up to the most recent one. Pretty convenient!

    Hope this helps or at least points you into the right direction!
     
    RavenOfCode likes this.
  3. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Thanks for the help,

    To answer your question, I am just using an int array to track the players, not a PhotonPlayers array.

    As far as updating the PlayerScript, I have been sending an RPC with the unit and were he is moving is that what you mean by EndTurn message?

    I completely forgot about PhotonTarget.AllBuffered, I will try using that. :)
     
  4. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    You might want to structure your game using messages, something like:

    Player 1 moves Unit 22 to position (4,3) ----- MoveMessage
    Player 1 orders Unit 22 to attack Unit 50 ----- AttackMessage
    Player 1 moves Unit 4 to position (10,10) ----- MoveMessage
    Player 1 activates Unit 6 special ability ----- ActivateMessage
    Player 1 passes turn to next player ----- EndTurnMessage

    Also, if your game will be multiplayer, you might want to use Client-Server approach where one player is Server.

    Clients would call:
    Code (CSharp):
    1. string json = message.ToString();
    2. photonView.RPC("ValidateMessage", PhotonTargets.MasterClient, json);
    That way, your master client will receive the message, allowing him to check if the move is possible or not. That way you can see if someone is cheating; like, if he moves 100 tiles but his move count is 8 max:
    Code (CSharp):
    1. //master client code
    2.  
    3. [PunRPC]
    4. void ValidateMessage(string json, PhotonMessageInfo info)
    5. {
    6.      Message msg = new Message(json);
    7.  
    8.      // validate if message is possible on master client, to prevent cheating
    9.      bool isValid = ...
    10.    
    11.      if (isValid)
    12.      {
    13.           photonView.RPC("EnqueueMessage", PhotonTargets.AllBuffered, json);
    14.      }
    15.      else
    16.      {
    17.           //handle cheater here, kick him out or w/e
    18.      }
    19. }
    If everything is alright, you can send the message to all clients, even the master client himself to update game state.

    Also, when you have your moves like messages they can be saved as json to disk and later retrieved, allowing you to recreate all steps for your match Replay feature :)
     
    RavenOfCode likes this.
  5. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Wow thanks for the tips, that makes alot of sense I will try using that! :)