- Home /
Random Server/Client Desync
Alright, so I've been messing around with authoritative network lately, and I've come across a problem that I just can't solve. My problem is that every time the player jumps, it will cause an eventual desync with the server, consistently. It can be reproduced by rapidly tapping the space bar(jump key) when the player approaches the ground. It's possible that this is caused by inconsistencies with the raycast in some way, but I'm not sure. One very important thing to note is that the client jumps after the keyboard spam, but the server does not.
Steps I've taken to prevent desync:
Identical code on sever and client
Identical execution order
Identical framerate(FixedUpdate)
Anyway, my code is below. Can you guys see if I'm missing something that would cause the desync? Thanks!
EDIT: Just to clarify, I am aware of a few security flaws in my code, ignore them. It's just a test. Also, the object this would be applied to would be owned by the server. The NetworkInfo component would contain the client "owner"(NetworkPlayer) of the object, returned by GetID.
var layerMask : LayerMask;
var skinWidth : float = 0.1;
var forwardSpeed : int = 1;
var backSpeed : int = 1;
var sideSpeed : int = 1;
var smoothingFactor : float = 1.0;
var framesToSend : int = 5;
var jumpHeight : float = 2;
private var minimumExtent : float;
private var partialExtent : float;
private var sqrMinimumExtent : float;
private var previousPosition : Vector3;
private var myRigidbody : Rigidbody;
private var internalGround : boolean = false;
private var rpcGot : boolean;
private var resultServer : Vector3;
private var movementsString : String = "";
private var tempArray = new Array();
private var tempVectorLength : int = 0;
private var isGrounded : boolean = true;
function Awake() {
myRigidbody = rigidbody;
previousPosition = myRigidbody.position;
minimumExtent = Mathf.Min(Mathf.Min(collider.bounds.extents.x, collider.bounds.extents.y), collider.bounds.extents.z);
partialExtent = minimumExtent*(1.0 - skinWidth);
sqrMinimumExtent = minimumExtent*minimumExtent;
}
function FixedUpdate() {
if(Network.isClient) {
networkView.observed = null;
var movementThisStep : Vector3 = myRigidbody.position - previousPosition;
var movementSqrMagnitude : float = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent) {
var movementMagnitude : float = Mathf.Sqrt(movementSqrMagnitude);
var hitInfo : RaycastHit;
if (Physics.Raycast(previousPosition, movementThisStep, hitInfo, movementMagnitude, layerMask.value))
myRigidbody.position = hitInfo.point - (movementThisStep/movementMagnitude)*partialExtent;
}
previousPosition = myRigidbody.position;
if(Input.GetKey(KeyCode.W)) {
movementsString += "1,";
var cvels = rigidbody.velocity;
var tvels = transform.forward * forwardSpeed;
rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
} else {
movementsString += "0,";
}
if(Input.GetKey(KeyCode.S)) {
movementsString += "1,";
cvels = rigidbody.velocity;
tvels = -transform.forward * forwardSpeed;
rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
} else {
movementsString += "0,";
}
if(Input.GetKey(KeyCode.A)) {
movementsString += "1,";
cvels = rigidbody.velocity;
tvels = -transform.right * sideSpeed;
rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
} else {
movementsString += "0,";
}
if(Input.GetKey(KeyCode.D)) {
movementsString += "1,";
cvels = rigidbody.velocity;
tvels = transform.right * sideSpeed;
rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
} else {
movementsString += "0,";
}
if(Input.GetKeyDown(KeyCode.Space) && Physics.Raycast(this.gameObject.transform.position, -transform.up, 1.0) && isGrounded) {
Grounded();
movementsString += "1,";
//cvels = rigidbody.velocity;
//tvels = transform.up * jumpHeight;
//rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
rigidbody.velocity = transform.up * 10.0f;
} else {
movementsString += "0,";
}
var tempVector : Vector3 = this.gameObject.transform.rotation.eulerAngles;
movementsString += tempVector.x.ToString();
movementsString += ",";
tempVectorLength += tempVector.x.ToString().Length;
movementsString += tempVector.y.ToString();
movementsString += ",";
tempVectorLength += tempVector.y.ToString().Length;
movementsString += tempVector.z.ToString();
movementsString += ",";
tempVectorLength += tempVector.z.ToString().Length;
if(movementsString.Length == (framesToSend * 13) + tempVectorLength) {
networkView.RPC("SendInput", RPCMode.Server, Network.player, movementsString, this.gameObject.transform.position);
movementsString = "";
tempVectorLength = 0;
}
}
if(Network.isServer && rpcGot) {
if(tempArray[0] == "1") {
var cvel = rigidbody.velocity;
var tvel = transform.forward * forwardSpeed;
rigidbody.velocity = Vector3.Lerp(cvel, tvel, Time.fixedDeltaTime * smoothingFactor);
}
tempArray.RemoveAt(0);
if(tempArray[0] == "1") {
cvel = rigidbody.velocity;
tvel = -transform.forward * forwardSpeed;
rigidbody.velocity = Vector3.Lerp(cvel, tvel, Time.fixedDeltaTime * smoothingFactor);
}
tempArray.RemoveAt(0);
if(tempArray[0] == "1") {
cvel = rigidbody.velocity;
tvel = -transform.right * sideSpeed;
rigidbody.velocity = Vector3.Lerp(cvel, tvel, Time.fixedDeltaTime * smoothingFactor);
}
tempArray.RemoveAt(0);
if(tempArray[0] == "1") {
cvel = rigidbody.velocity;
tvel = transform.right * sideSpeed;
rigidbody.velocity = Vector3.Lerp(cvel, tvel, Time.fixedDeltaTime * smoothingFactor);
}
tempArray.RemoveAt(0);
if(tempArray[0] == "1" && Physics.Raycast(this.gameObject.transform.position, -transform.up, 1.0) && isGrounded) {
Grounded();
//cvels = rigidbody.velocity;
//tvels = transform.up * jumpHeight;
//rigidbody.velocity = Vector3.Lerp(cvels, tvels, Time.fixedDeltaTime * smoothingFactor);
rigidbody.velocity = transform.up * 10.0f;
}
tempArray.RemoveAt(0);
this.gameObject.transform.rotation.eulerAngles.x = float.Parse(tempArray[0]);
tempArray.RemoveAt(0);
this.gameObject.transform.rotation.eulerAngles.y = float.Parse(tempArray[0]);
tempArray.RemoveAt(0);
this.gameObject.transform.rotation.eulerAngles.z = float.Parse(tempArray[0]);
tempArray.RemoveAt(0);
if(tempArray.length < 8) {
tempArray.Clear();
rpcGot = false;
if(Vector3.Distance(this.gameObject.transform.position, resultServer) < 1) {
print("The player's pos matched");
} else {
print("The player's pos didn't match");
networkView.RPC("CorrectPos", GetComponent(NetworkInfo).GetID(), transform.position, transform.rotation.eulerAngles);
}
}
}
}
function Grounded() {
yield WaitForSeconds(0.2);
while(!Physics.Raycast(this.gameObject.transform.position, Vector3.down, 1.0)) {
isGrounded = false;
print("ff");
yield;
}
yield WaitForSeconds(0.2);
isGrounded = true;
}
@RPC
function SendInput(sender : NetworkPlayer, tempMov : String, pos : Vector3) {
if(GetComponent(NetworkInfo).GetID() == sender) {
tempArray = new Array(tempMov.Split(","[0]));
resultServer = pos;
rpcGot = true;
} else {
print("Permissions Err");
}
}
@RPC
function CorrectPos(pos : Vector3, rot : Vector3) {
transform.position = pos;
transform.rotation.eulerAngles = rot;
}
Your answer

Follow this Question
Related Questions
Network Client does not Groundcheck 0 Answers
Unity networking tutorial? 6 Answers
Photon Vikign Demo Jump animation issue 0 Answers
Multiplayer Password 0 Answers
how do you send commands from objects that dont have "Authortiy" unet 1 Answer