Hi… here’s a translated version of the Network Tutorials “NetworkInterpolatedTransform.cs” into JavaScript. It helps with the network transform predictions. I couldn’t get the C# version of the script to work with my CharacterControllers, and perhaps someone else might need this script.
var interpolationBackTime = 0.1;
private var m_BufferedState : Array = new State[20]; // where we store the State of our controller
private var m_TimestampCount : int; // keeps track of what slots are used
// Holds information about the controllers movements and last sent information from the network
class State
{
var timeStamp : float;
var pos : Vector3;
var rot : Quaternion;
}
function OnSerializeNetworkView(stream : BitStream, info : NetworkMessageInfo)
{
if (stream.isWriting)
{
var pos = transform.position;
var rot = transform.rotation;
stream.Serialize(pos);
stream.Serialize(rot);
}
else
{
pos = Vector3.zero;
rot = Quaternion.identity;
stream.Serialize(pos);
stream.Serialize(rot);
for (var i = m_BufferedState.length - 1; i >= 1; i --)
{
m_BufferedState[i] = m_BufferedState[i-1];
}
var state = new State();
state.timeStamp = info.timestamp;
state.pos = pos;
state.rot = rot;
m_BufferedState[0] = state;
m_TimestampCount = Mathf.Min(m_TimestampCount + 1, m_BufferedState.length);
for (i = 0; i < m_TimestampCount-1; i++)
{
if (m_BufferedState[i].timeStamp < m_BufferedState[i+1].timeStamp)
{
Debug.Log("State inconsistent");
}
}
}
}
function Update ()
{
if (!networkView.isMine)
{
var currentTime = Network.time;
var interpolationTime = currentTime - interpolationBackTime;
if (m_BufferedState[0] != null m_BufferedState[0].timeStamp > interpolationTime)
{
for (var i = 0; i < m_TimestampCount; i++)
{
if (m_BufferedState[i].timeStamp <= interpolationTime || i == m_TimestampCount - 1)
{
// The state one slot newer (<100ms) than the best playback state
var rhs : State = m_BufferedState[Mathf.Max(i-1, 0)];
// The best playback state (closest to 100 ms old (default time))
var lhs : State = m_BufferedState[i];
// Use the time between the two slots to determine if interpolation is necessary
var length = rhs.timeStamp - lhs.timeStamp;
var t : float = 0.0;
if (length > 0.0001)
{
t = ((interpolationTime - lhs.timeStamp) / length);
}
// if t=0 => lhs is used directly
transform.position = Vector3.Lerp(lhs.pos, rhs.pos, t);
transform.rotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
return;
}
}
}
else
{
if (m_BufferedState[0] != null)
{
var latest = m_BufferedState[0];
transform.position = latest.pos;
transform.rotation = latest.rot;
}
}
}
}
To use it, just drop the script onto your CharacterController, attach a NetworkView, and set the NetworkView to observe the script. Good luck…