69 lines
3.0 KiB
C#
69 lines
3.0 KiB
C#
|
// snapshot for snapshot interpolation
|
||
|
// https://gafferongames.com/post/snapshot_interpolation/
|
||
|
// position, rotation, scale for compatibility for now.
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Mirror
|
||
|
{
|
||
|
// NetworkTransform Snapshot
|
||
|
public struct TransformSnapshot : Snapshot
|
||
|
{
|
||
|
// time or sequence are needed to throw away older snapshots.
|
||
|
//
|
||
|
// glenn fiedler starts with a 16 bit sequence number.
|
||
|
// supposedly this is meant as a simplified example.
|
||
|
// in the end we need the remote timestamp for accurate interpolation
|
||
|
// and buffering over time.
|
||
|
//
|
||
|
// note: in theory, IF server sends exactly(!) at the same interval then
|
||
|
// the 16 bit ushort timestamp would be enough to calculate the
|
||
|
// remote time (sequence * sendInterval). but Unity's update is
|
||
|
// not guaranteed to run on the exact intervals / do catchup.
|
||
|
// => remote timestamp is better for now
|
||
|
//
|
||
|
// [REMOTE TIME, NOT LOCAL TIME]
|
||
|
// => DOUBLE for long term accuracy & batching gives us double anyway
|
||
|
public double remoteTime { get; set; }
|
||
|
|
||
|
// the local timestamp (when we received it)
|
||
|
// used to know if the first two snapshots are old enough to start.
|
||
|
public double localTime { get; set; }
|
||
|
|
||
|
public Vector3 position;
|
||
|
public Quaternion rotation;
|
||
|
public Vector3 scale;
|
||
|
|
||
|
public TransformSnapshot(double remoteTime, double localTime, Vector3 position, Quaternion rotation, Vector3 scale)
|
||
|
{
|
||
|
this.remoteTime = remoteTime;
|
||
|
this.localTime = localTime;
|
||
|
this.position = position;
|
||
|
this.rotation = rotation;
|
||
|
this.scale = scale;
|
||
|
}
|
||
|
|
||
|
public static TransformSnapshot Interpolate(TransformSnapshot from, TransformSnapshot to, double t)
|
||
|
{
|
||
|
// NOTE:
|
||
|
// Vector3 & Quaternion components are float anyway, so we can
|
||
|
// keep using the functions with 't' as float instead of double.
|
||
|
return new TransformSnapshot(
|
||
|
// interpolated snapshot is applied directly. don't need timestamps.
|
||
|
0, 0,
|
||
|
// lerp position/rotation/scale unclamped in case we ever need
|
||
|
// to extrapolate. atm SnapshotInterpolation never does.
|
||
|
Vector3.LerpUnclamped(from.position, to.position, (float)t),
|
||
|
// IMPORTANT: LerpUnclamped(0, 60, 1.5) extrapolates to ~86.
|
||
|
// SlerpUnclamped(0, 60, 1.5) extrapolates to 90!
|
||
|
// (0, 90, 1.5) is even worse. for Lerp.
|
||
|
// => Slerp works way better for our euler angles.
|
||
|
Quaternion.SlerpUnclamped(from.rotation, to.rotation, (float)t),
|
||
|
Vector3.LerpUnclamped(from.scale, to.scale, (float)t)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public override string ToString() =>
|
||
|
$"TransformSnapshot(remoteTime={remoteTime:F2}, localTime={localTime:F2}, pos={position}, rot={rotation}, scale={scale})";
|
||
|
}
|
||
|
}
|