-
Notifications
You must be signed in to change notification settings - Fork 461
Expand file tree
/
Copy pathSyncTransform.cs
More file actions
142 lines (126 loc) · 4.73 KB
/
SyncTransform.cs
File metadata and controls
142 lines (126 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using MLAPI.NetworkedVar;
using UnityEngine;
namespace MLAPI
{
/// <summary>
/// A component for syncing variables
/// Initial goal: allow an FPS-style snapshot
/// with variables updating at specific place in the frame
/// </summary>
[AddComponentMenu("MLAPI/SyncTransform")]
// todo: check inheriting from NetworkedBehaviour. Currently needed for IsLocalPlayer, to synchronize position
public class SyncTransform : NetworkedBehaviour
{
private NetworkedVar<Vector3> m_VarPos = new NetworkedVar<Vector3>();
private NetworkedVarQuaternion m_VarRot = new NetworkedVarQuaternion();
private const float k_Epsilon = 0.001f;
private bool m_Interpolate = true;
// data structures for interpolation
private Vector3[] m_PosStore = new Vector3[2];
private Quaternion[] m_RotStore = new Quaternion[2];
private float[] m_PosTimes = new float[2];
private float[] m_RotTimes = new float[2];
private float m_LastSent = 0.0f;
SyncTransform()
{
m_PosTimes[0] = -1.0f;
m_PosTimes[1] = -1.0f;
m_RotTimes[0] = -1.0f;
m_RotTimes[1] = -1.0f;
m_VarPos.OnValueChanged = SyncPosChanged;
m_VarRot.OnValueChanged = SyncRotChanged;
}
void SyncPosChanged(Vector3 before, Vector3 after)
{
if (!IsLocalPlayer)
{
m_PosTimes[0] = m_PosTimes[1];
m_PosTimes[1] = Time.time;
m_PosStore[0] = m_PosStore[1];
m_PosStore[1] = after;
if (!m_Interpolate)
{
gameObject.transform.position = after;
}
}
}
void SyncRotChanged(Quaternion before, Quaternion after)
{
// todo: this is problematic. Why couldn't this filtering be done server-side?
if (!IsLocalPlayer)
{
m_RotTimes[0] = m_RotTimes[1];
m_RotTimes[1] = Time.time;
m_RotStore[0] = m_RotStore[1];
m_RotStore[1] = after;
if (!m_Interpolate)
{
gameObject.transform.rotation = after;
}
}
}
void Start()
{
m_VarPos.Settings.WritePermission = NetworkedVarPermission.Everyone;
m_VarRot.Settings.WritePermission = NetworkedVarPermission.Everyone;
}
void FixedUpdate()
{
float now = Time.time;
if (m_LastSent == 0.0f)
{
m_LastSent = now;
}
// if this.gameObject is local let's send its position
if (IsLocalPlayer)
{
m_VarPos.Value = gameObject.transform.position;
m_VarRot.Value = gameObject.transform.rotation;
}
else
{
if (!m_Interpolate)
{
return;
}
// let's m_Interpolate the last received transform
if (m_PosTimes[0] >= 0.0 && m_PosTimes[1] >= 0.0)
{
var before = gameObject.transform.position;
if (m_PosTimes[1] - m_PosTimes[0] > k_Epsilon)
{
if ((now - m_PosTimes[0]) / (m_PosTimes[1] - m_PosTimes[0]) < 2.0)
{
gameObject.transform.position = Vector3.LerpUnclamped(
m_PosStore[0],
m_PosStore[1],
(now - m_PosTimes[0]) / (m_PosTimes[1] - m_PosTimes[0]));
}
}
else
{
gameObject.transform.position = m_PosStore[1];
}
}
if (m_RotTimes[0] >= 0.0 && m_RotTimes[1] >= 0.0)
{
var before = gameObject.transform.rotation;
if (m_RotTimes[1] - m_RotTimes[0] > k_Epsilon)
{
if ((now - m_RotTimes[0]) / (m_RotTimes[1] - m_RotTimes[0]) < 2.0)
{
gameObject.transform.rotation = Quaternion.SlerpUnclamped(
m_RotStore[0],
m_RotStore[1],
(now - m_RotTimes[0]) / (m_RotTimes[1] - m_RotTimes[0]));
}
}
else
{
gameObject.transform.rotation = m_RotStore[1];
}
}
}
}
}
}