Search Unity

RTS-like movement with the server computing all movement

Discussion in 'Multiplayer' started by norathem, Sep 2, 2015.

  1. norathem

    norathem

    Joined:
    Sep 30, 2014
    Posts:
    2
    So, I just started to try and develop my first multiplayer prototyp. I plan on using UNet but it seems like there isn't a lot of tutorials/help/etc. out there already. I found a few helpfull infos though. My problem is that most of them are meant for first person style games and just sync the movement a player makes - so maybe if you know something thats more fitting to my case I'd be thankfull :)

    Anyways, what I try to achieve is a controll scheme similar to RTS, MOBA, Hack 'n Slay (so practically mouse click to move). Also the server should do all the movement, player only send in theire orders/mouse click (to prevent cheating).

    I created something that works, howerver movement is still quite stuttering so I'd be glad if you could give me some pointers of what I'm doing wrong.
    Here's my code so far

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class Player_SyncPosition : NetworkBehaviour {
    6.  
    7.  
    8.     [SyncVar]
    9.     private Vector3 syncPos;
    10.  
    11.     private bool isMoving = false;
    12.     private Vector3 endPos;
    13.  
    14.     [SerializeField]
    15.     Transform myTransform;
    16.  
    17.     [SerializeField]
    18.     float lerpRate = 15;
    19.  
    20.     [SerializeField]
    21.     float speed = 10f;
    22.  
    23.     //vertical position of the gameobject
    24.     private float yAxis;
    25.  
    26.  
    27.     void Start()
    28.     {
    29.         //save the y axis value of gameobject
    30.         yAxis = gameObject.transform.position.y;
    31.     }
    32.  
    33.     void FixedUpdate () {
    34.         if (hasAuthority)
    35.         {
    36.             Cmd_UpdateMovement();
    37.         }  
    38.     }
    39.  
    40.     void Update()
    41.     {
    42.         if (isLocalPlayer)
    43.         {
    44.             CheckForClick();
    45.         }
    46.         LerpPosition();
    47.     }
    48.  
    49.     [ClientCallback]
    50.     void CheckForClick()
    51.     {
    52.         if (Input.GetMouseButtonDown(0))
    53.         {
    54.             //declare a variable of RaycastHit struct
    55.             RaycastHit hit;
    56.             //Create a Ray on the clicked position
    57.             Ray ray;
    58.  
    59.             ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    60.  
    61.             //Check if the ray hits any collider
    62.             if (Physics.Raycast(ray, out hit))
    63.             {
    64.                 //save the click position
    65.                 Vector3 clickPos = hit.point;
    66.                 //reset to original y axis value
    67.                 clickPos.y = yAxis;
    68.                 Cmd_ComputeMovementPoint(clickPos);
    69.             }
    70.         }
    71.     }
    72.  
    73.     void LerpPosition()
    74.     {
    75.         myTransform.position = Vector3.Lerp(myTransform.position, syncPos, Time.deltaTime * lerpRate);
    76.     }
    77.  
    78.     [Command]
    79.     void Cmd_ComputeMovementPoint(Vector3 pos)
    80.     {
    81.         endPos = pos;
    82.         //set a flag to indicate that the gameobject is moving
    83.         isMoving = true;
    84.      
    85.     }
    86.  
    87.     [Command]
    88.     void Cmd_UpdateMovement()
    89.     {
    90.         if (isMoving && !Mathf.Approximately(myTransform.position.magnitude, endPos.magnitude))
    91.         {
    92.             //move the gameobject to the desired position
    93.             myTransform.position = Vector3.Lerp(myTransform.position, endPos, 1 / (speed * (Vector3.Distance(myTransform.position, endPos))));
    94.             syncPos = myTransform.position;
    95.         }
    96.         //set the movement indicator flag to false if the endPoint and current gameobject position are equal
    97.         else if (isMoving && Mathf.Approximately(myTransform.position.magnitude, endPos.magnitude))
    98.         {
    99.             isMoving = false;
    100.         }
    101.     }
    102. }
    103.  
     
  2. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Currently working on an RTS multiplayer game in Unity 5.1.3.

    Instead of using lerps to handle movement, I would suggest you to try using NavMeshAgent + NavMesh + send 1 Vector3 point, and have the unit with the NavMeshAgent component added to it to navigate towards that 1 Vector3 point. The movement will be limited, but it will definitely be smoother.

    Before you continue, see if you can try selecting your units (preferably, buildings or spawners), and try spawning a unit. This is the part that stumps me more often than not. And I would like someone else who are tackling the RTS genre and its subgenres to work on spawning units first before handling other parts of the unit movement. I currently do not have any idea how to fix this problem.