TransformSnapshot.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // snapshot for snapshot interpolation
  2. // https://gafferongames.com/post/snapshot_interpolation/
  3. // position, rotation, scale for compatibility for now.
  4. using UnityEngine;
  5. namespace Mirror
  6. {
  7. // NetworkTransform Snapshot
  8. public struct TransformSnapshot : Snapshot
  9. {
  10. // time or sequence are needed to throw away older snapshots.
  11. //
  12. // glenn fiedler starts with a 16 bit sequence number.
  13. // supposedly this is meant as a simplified example.
  14. // in the end we need the remote timestamp for accurate interpolation
  15. // and buffering over time.
  16. //
  17. // note: in theory, IF server sends exactly(!) at the same interval then
  18. // the 16 bit ushort timestamp would be enough to calculate the
  19. // remote time (sequence * sendInterval). but Unity's update is
  20. // not guaranteed to run on the exact intervals / do catchup.
  21. // => remote timestamp is better for now
  22. //
  23. // [REMOTE TIME, NOT LOCAL TIME]
  24. // => DOUBLE for long term accuracy & batching gives us double anyway
  25. public double remoteTime { get; set; }
  26. // the local timestamp (when we received it)
  27. // used to know if the first two snapshots are old enough to start.
  28. public double localTime { get; set; }
  29. public Vector3 position;
  30. public Quaternion rotation;
  31. public Vector3 scale;
  32. public TransformSnapshot(double remoteTime, double localTime, Vector3 position, Quaternion rotation, Vector3 scale)
  33. {
  34. this.remoteTime = remoteTime;
  35. this.localTime = localTime;
  36. this.position = position;
  37. this.rotation = rotation;
  38. this.scale = scale;
  39. }
  40. public static TransformSnapshot Interpolate(TransformSnapshot from, TransformSnapshot to, double t)
  41. {
  42. // NOTE:
  43. // Vector3 & Quaternion components are float anyway, so we can
  44. // keep using the functions with 't' as float instead of double.
  45. return new TransformSnapshot(
  46. // interpolated snapshot is applied directly. don't need timestamps.
  47. 0, 0,
  48. // lerp position/rotation/scale unclamped in case we ever need
  49. // to extrapolate. atm SnapshotInterpolation never does.
  50. Vector3.LerpUnclamped(from.position, to.position, (float)t),
  51. // IMPORTANT: LerpUnclamped(0, 60, 1.5) extrapolates to ~86.
  52. // SlerpUnclamped(0, 60, 1.5) extrapolates to 90!
  53. // (0, 90, 1.5) is even worse. for Lerp.
  54. // => Slerp works way better for our euler angles.
  55. Quaternion.SlerpUnclamped(from.rotation, to.rotation, (float)t),
  56. Vector3.LerpUnclamped(from.scale, to.scale, (float)t)
  57. );
  58. }
  59. public override string ToString() =>
  60. $"TransformSnapshot(remoteTime={remoteTime:F2}, localTime={localTime:F2}, pos={position}, rot={rotation}, scale={scale})";
  61. }
  62. }