Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualKylotan

Posted 08 March 2013 - 06:59 AM

Here's some C# sample code which I wrote just yesterday for the very simple client-side interpolation that I mentioned above:

 

public class CharacterMover
{
    private Vector3 actualPosition; // where we render

    private Vector3 latestPosition; // last position reported by server
    private float latestPositionTime; // the time we want to arrive at the last position reported by server
    private Vector3 previousPosition; // the previous point we're interpolating from
    bool isMoving = false;
    
    // Must be longer than the period between movement messages, plus a little extra to account
    // for network jitter. 0.3f is ok for MMOs and strategic RPGs, probably too high for RTSs,
    // MOBAs, and action RPGs. Far too high for FPSs which need a more complex system than this.
    public float InterpolationPeriod = 0.3f; 
   
    // Update is called once per frame
    void Update ()
    {
        if (isMoving)
        {
            float t = 1.0f - ((latestPositionTime - Time.NOW) / InterpolationPeriod);
            actualPosition = Vector3.Lerp(previousPosition, latestPosition, t);
        }
        else
        {
            actualPosition = latestPosition;
        }

        // TODO: move sprite or 3D model to actualPosition and render it there
    }
    
    // Call this whenever you get a message from the server notifying this client of the character's new
    // position and it's quite close to the current position
    public void SetPosition(Vector3 newPosition)
    {
        isMoving = true;
        
        // Set this as a future position to arrive at, and interpolate between the
        // current position and future position in Update()
        latestPosition = newPosition;
        latestPositionTime = Time.NOW + InterpolationPeriod;
        previousPosition = actualPosition;
    }
    
    // Call this whenever you get a message from the server notifying this client of the character's new position and
    // it's NOT close to the current position, OR you need to perform an instant correction, OR you just want to stop the
    // character still in a certain spot.
    public void SnapToPosition(Vector3 newPosition)
    {
        isMoving = false;
        // move directly there, do not pass go, do not collect $200
        previousPosition = latestPosition = newPosition;
        latestPositionTime = Time.NOW;
        actualPosition = latestPosition;
    }

}
 

It's not intended to be AAA quality tested code, and there are some bugs unhandled edge-cases in there, but it does a decent enough job of keeping movement of networked characters smooth at fairly low movement speeds and infrequent changes in velocity/direction.

: disclaimers in the code!


#1Kylotan

Posted 08 March 2013 - 06:57 AM

Here's some C# sample code which I wrote just yesterday for the very simple client-side interpolation that I mentioned above:

 

public class CharacterMover
{
    private Vector3 actualPosition; // where we render

    private Vector3 latestPosition; // last position reported by server
    private float latestPositionTime; // the time we want to arrive at the last position reported by server
    private Vector3 previousPosition; // the previous point we're interpolating from
    bool isMoving = false;
    
    public float InterpolationPeriod = 0.3f; // should be longer than the period between movement messages, plus a little extra to account for network jitter
   
    // Update is called once per frame
    void Update ()
    {
        if (isMoving)
        {
            float t = 1.0f - ((latestPositionTime - Time.NOW) / InterpolationPeriod);
            actualPosition = Vector3.Lerp(previousPosition, latestPosition, t);
        }
        else
        {
            actualPosition = latestPosition;
        }

        // TODO: move sprite or 3D model to actualPosition and render it there
    }
    
    // Call this whenever you get a message from the server notifying this client of the character's new
    // position and it's quite close to the current position
    public void SetPosition(Vector3 newPosition)
    {
        isMoving = true;
        
        // Set this as a future position to arrive at, and interpolate between the
        // current position and future position in Update()
        latestPosition = newPosition;
        latestPositionTime = Time.NOW + InterpolationPeriod;
        previousPosition = actualPosition;
    }
    
    // Call this whenever you get a message from the server notifying this client of the character's new position and
    // it's NOT close to the current position, OR you need to perform an instant correction, OR you just want to stop the
    // character still in a certain spot.
    public void SnapToPosition(Vector3 newPosition)
    {
        isMoving = false;
        // move directly there, do not pass go, do not collect $200
        previousPosition = latestPosition = newPosition;
        latestPositionTime = Time.NOW;
        actualPosition = latestPosition;
    }

}
 

It's not intended to be AAA quality tested code, and there are some bugs unhandled edge-cases in there, but it does a decent enough job of keeping movement of networked characters smooth at fairly low movement speeds and infrequent changes in velocity/direction.


PARTNERS