- Home /
Choppy player movement on clients' devices but not on authoritative server using UNet
Hello guys,
I have been working on these scripts for a week in hopes of making a small multiplayer game with authoritative server. So far I was able to get everything moving well and smooth along with interpolation until I introduced the concept of running vs walking. Once I did, for some odd reason my player objects appear on the server extremely smooth. However, on clients, they appear pretty choppy -- even the local player object to the client is choppy but smooth on the server.
The scripts work in this way; PlayerInput detects the player input and according to it, sends the input to the server. The server uses PlayerMovement script to move the player according to the input it receives. Finally, the Stats script deal with various stats for the player such as HP, energy and stamina (stamina used for running).
Here are the scripts:
PlayerInput script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class PlayerInput : NetworkBehaviour {
private float horizontalInput;
private float verticalInput;
private PlayerMovement playerMovement;
private bool transmitPosition = true;
private void Start()
{
playerMovement = GetComponent<PlayerMovement>();
}
private void Update()
{
if(isLocalPlayer)
{
SendInputToServer();
}
}
void SendInputToServer()
{
InputMovement();
InputRunning();
if (transmitPosition)
playerMovement.CmdApplyMovement(horizontalInput, verticalInput);
}
void InputMovement()
{
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
if (horizontalInput == 0 && verticalInput == 0)
transmitPosition = false;
else
transmitPosition = true;
}
void InputRunning()
{
if (Input.GetAxisRaw("Fire3") != 0)
playerMovement.CmdActivateRunning();
else
playerMovement.CmdDeactivateRunning();
}
}
PlayerMovement script:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerMovement : NetworkBehaviour
{
[SyncVar(hook = "UpdateMovement")] private Vector2 position;
[SerializeField] private float walkSpeed = 15;
[SerializeField] private float runSpeed = 35;
private float lerpRate = 15;
[SyncVar] private ushort isRunning = 0; // 0 is false and 1 is true. This is to reduce the data sent over network.
private Rigidbody2D rb;
private Stats playerStats;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
playerStats = GetComponent<Stats>();
}
[Command]
public void CmdApplyMovement(float mHorizontal, float mVertical)
{
float x;
float y;
if (isRunning == 0)
{
x = mHorizontal * walkSpeed * Time.deltaTime;
y = mVertical * walkSpeed * Time.deltaTime;
}
else
{
x = mHorizontal * runSpeed * Time.deltaTime;
y = mVertical * runSpeed * Time.deltaTime;
}
position = (Vector2)transform.position + new Vector2(x, y);
}
[Command]
public void CmdActivateRunning()
{
if (isRunning == 0 && playerStats.currentStamina > 0)
isRunning = 1;
if (isRunning == 1)
playerStats.CmdReduceStamina(playerStats.costOfRunning);
}
[Command]
public void CmdDeactivateRunning()
{
if (isRunning == 1)
isRunning = 0;
}
void UpdateMovement(Vector2 _pos) // A hooked function to the SyncVar Position for when it updates, it calls this function and as such moves
{
// Lerping is added to the movement because clients are dumb, so we simulate movement on all of them rather than them moving locally.
if (rb.position != _pos)
rb.MovePosition(Vector3.Lerp(rb.position, _pos, lerpRate * Time.deltaTime));
}
}
Finally the Stats script:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking;
public class Stats : NetworkBehaviour {
[SyncVar] public int currentHealth;
[SyncVar] public int maxHealth;
[SyncVar] public int currentEnergy;
[SyncVar] public int maxEnergy;
[SyncVar] public int currentStamina;
[SyncVar] public int maxStamina;
[SyncVar] public int costOfRunning = 2; // Until I change running into a skill and create skills.
public string playerName;
public bool canAttack;
public bool canScan; // This is for the scanning module if it was activated to get more information about things and display items highlighted.
private PlayerMovement playerMovement;
private void Awake()
{
currentHealth = maxHealth;
currentEnergy = maxEnergy;
currentStamina = maxStamina;
playerMovement = GetComponent<PlayerMovement>();
}
[Command]
public void CmdReduceStamina(int amount)
{
if (currentStamina >= amount)
StartCoroutine("DecreaseStaminaPerSecond");
else
{
currentStamina = 0;
playerMovement.CmdDeactivateRunning();
}
}
IEnumerator DecreaseStaminaPerSecond()
{
yield return new WaitForSeconds(1);
currentStamina -= costOfRunning;
StopCoroutine("DecreaseStaminaPerSecond");
}
#endregion
}
Any help would be greatly appreciated.
Your answer
Follow this Question
Related Questions
Unity networking tutorial? 6 Answers
Best cross platform Http Library? 1 Answer
How to use NetworkManager.ServerChangeScene ? 1 Answer
Network Connection Works Locally, but not Publicly 0 Answers