Open delgelato opened 3 years ago
Another alternative i'm wondering, actually
So this desync is caused by
So based on these points, i wonder if.... server should just NOT re-simulate .Move, and instead lerp between the move packets.
Bcoz really, server being drunk thinking move packet has invalid speed is only bcoz of its own failure to resimulate as how it was simulated in client
I did check the incoming packets by the time it's received (instead of when it's processed), and none of them are invalid..
So yeah, why server have to resimulate, right?
Actually it does need to.. bcoz in the case of lag, client's environment might not be up to date. If server complies without questioning client's Cc.Move, then possibly client will be walking through a newly spawned obstacle
Another theory is: The other reason the simulation is non deterministic is bcoz client sends pos after Cc.Move(input*speed) Whereas server simulates with Cc.Move(movePacket.pos - current transform.pos)
Proof:
Transform.position result of server after doing server's CC.Move is mostly different than the received movePacket.position
I added the following:
if(transform.position != next.position) { Vector3 dif = next.position - transform.position; Debug.Log("Dif after server Cc.Move: " + dif + " mag: " + dif.magnitude); }
And the result (and a move rejected at the end of it):
So as i suspected, the position difference is accumulating, and when the difference of (nextPacket.position - transform.position) in server is too large, move rejected is called
edit: It's not accumulating, because next frame's Cc.Move will simply just start at whatever current transform.position towards nextPacket.position. And as long as it's less than 120% (the default tolerance), then the server will "correct" itself
A better debug test
if(transform.position != next.position) { Vector3 dif = next.position - transform.position; Vector2 flatMove = new Vector2(move.x, move.z) / Time.fixedDeltaTime; Vector2 flatVelo = new Vector2(velocity.x, velocity.z); Debug.Log(NetworkTime.time + " Dif after server Cc.Move: " + dif + " mag: " + dif.magnitude + "\nmove: " + flatMove.magnitude + " velo: " + flatVelo.magnitude); }
And also adding NetworkTime.time in the move rejected message, to find that the desync pos is never at the same frame as the move rejected
Move rejected happens only AFTER the result of previous frame's Cc.Move in server was somehow slower/more obstructed than it should.
This frame's offending Cc.Move landed 100% exactly at nextPacket.position(hence it doesn't call the first Debug.Log), except that it started at a more behind starting transform.position caused by the previous frame's slowness.
Maybe this is when, in the server, the move was right after the chara was "free" from the obstruction of the wall (unobstructed straight Cc.Move)
So it seems there's a desync in how server handles the move packet coming from clients, when bumping to stuff. Maybe a split second difference between when exactly the unit stops "walking against" the wall/collider/stuff. Client thinks that he's already free from getting bumped, thus keeps walking, while the result of controller.Move in server, which is the value of controller.velocity right after, is not a value that's valid for a non-bumping unit, thus the server gets position value (perhaps on the next frame) much larger than the valid speed
This happens in the non-combined move, but sometimes even in the combined move too. In the non-combined, worst invalid value was like, 9.8 / 6 (that's almost 200% the original valid speed, which is 5)
Tested on Unity 2019.4.13f1 Using uMMORPG CE 2.20
Lines to check: PCCM.FixedUpdate 1160
if (!WasValidSpeed(velocity, previousState, state, false))
The other related issue is, (or, a critic), i dont think
Warp()
ing the player when they go over the speed limit is a good thing. Quoting my convo with Chismar on discord:Also an alternative way that i'm currently trying is this:
So basically, i dont think Warp() is the most correct thing to do for server invalidation, because pendingMove is cleared and that's potentially 3 pending moves in the server, PLUS whatever movement the client's already doing on their end before they get the Warp (considering RTT, maybe 6-7 frames of move gone) But of course before going to the usage of Warp, first is the issue of why this is happening. The slight de-sync when walking into obstacles is the cause, and i'm still not sure exactly what's the best way to handle this The detailed "cause" of this is mentioned in the beginning of the post, but i'm only like 80-90% sure that this is exactly what's happening
Cheers