Thursday, October 17, 2019

Improved Smoothness

A problem with Broadside: Perilous Waters has been the smoothness of the client side movement of objects, such as ships and cannonballs.  When I replaced Unet with the in house JCGNetwork system, I wrote a script called JCGNetworkTransform, which basically fills the role of Unet's NetworkTransform.  Essentially it syncs the position of an object from the server to the client. 

Now the NetworkTransform component from Unet was poorly documented, buggy, and overall didn't work very well.  JCGNetworkTransform was marginally better originally but would result in jittery motion especially for objects at high speed.  It has several modes, but the one I primarily used I called SmoothRB.  It would sync the current position, rotation, physics velocity, and angular velocity.  The client would apply the two physics values and apply the position and rotation over time between receiving new updates. 

In theory it seemed like it would work well, but the result was updates from the server don't come in at an exactly regular rate, and it was difficult to smoothly transition between the last position and the new position while the client was applying its own physics simulation.  I worked around this issue at the time by maxing out the send rate to match the server side 25 FPS.  But this just shrunk the problem instead of eliminating it, and created a new problem where the maximum number of players per server would be lower. 

Now I've written a new simple Interpolate mode.  It works by maintaining a queue of incoming position/rotation updates on the client and tries to keep to a specific target count in the queue.  Currently the queue target is just 1 so it is more responsive, but sometimes I may want to target a higher queue.  A higher queue count would reduce the chance that the client attempts to move the object but the next update hasn't yet arrives, at the expense of being further behind the position on the server. 

So now the server in these updates sends the current time, and the client can then interpolate between the last update and the current update being processed for the same amount of time the server took between those updates.  If the client gets behind replaying these updates it ever so slightly increases the speed it processes them in order to catch up over time, and if it gets ahead it either pauses or slightly slows down the movement.  All physics simulation on the client side is now disabled when in Interpolate mode. 

This has resulted in a much smoother movement of object movements, both ships and cannonballs, than before.  I'm still tuning the system, but it is looking good.  I've also increased the server side FPS and physics updates from 25 FPS to 32 FPS, and reduced the position update frequency from 25 FPS to 16 FPS.  The former was done to address an issue with very fast moving cannonballs from long guns flying through the smallest ships at close range without registering a hit.  Originally it was set so low to help with a CPU usage problem on the server side, but other improvements to address this over the past few months have allowed a little more head room to raise this back up again a bit. 

Hope you found this at all interesting.  This stuff will be included in 0.8.1. 

No comments:

Post a Comment