Interpolation for Character movement
Options
Guys Your help is very necessary with the decision of a problem of movement of the hero!
I studied the principle of interpolation for more than a month spent studying only this module but could not achieve a good result
It ("OnPhotonSerializeView") transmits 10 positions instead of 60 positions per second.
the game is a 3d arena,
where the two teams play against each other what's the matter if the lags start when 3 players play ?!
and it is necessary that there were 6 people in one room!
what am I doing wrong?
//*** interpolation property ***
private Vector3 oldCorrectPos;
private Quaternion latestCorrectRot;
private double firstServerTime;
private float firstLocalTime = -1;
private float tickDelta;
private List _buffer = new List(10);
private int skipFirstFramesCount;
void Start () {
if (photonView.isMine) {
//....
} else {
tickDelta = 1f / PhotonNetwork.sendRateOnSerialize;
skipFirstFramesCount = 30;
}
}
private static string PrintBuffer(List buffer)
{
var result = string.Empty;
for (int i = 0; i < buffer.Count; i++) {
result += buffer[i].time + " ";
}
return result;
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
if(stream.isWriting) {
Vector3 pos = transform.position;
Quaternion rot = transform.rotation;
stream.SendNext(pos);
stream.SendNext(rot);
stream.SendNext(anim.GetBool ("IsMove"));
stream.SendNext(anim.GetBool ("IsAttack"));
} else {
var position = (Vector3)stream.ReceiveNext();
var rotation = (Quaternion)stream.ReceiveNext();
anim.SetBool ("IsMove", (bool)stream.ReceiveNext ());
anim.SetBool ("IsAttack", (bool)stream.ReceiveNext ());
if (skipFirstFramesCount > 0) {
skipFirstFramesCount--;
return;
}
if (firstLocalTime == -1) {
firstServerTime = info.timestamp;
firstLocalTime = Time.time;
Debug.Log(Time.frameCount + ": delta: " + (PhotonNetwork.time - info.timestamp));
}
Debug.Log(Time.frameCount + ": Server Time: " + (float) (info.timestamp - firstServerTime));
_buffer.Add(
new TimedPosition {
time = (float) (info.timestamp - firstServerTime),
position = position
}
);
latestCorrectRot = rotation;
}
}
void Update () {
if (photonView.isMine) { // if this object is under our control, we don't need to apply received position-updates
return;
}
if (skipFirstFramesCount > 0) {
return;
}
transform.rotation = Quaternion.Lerp(transform.rotation, latestCorrectRot, (Time.deltaTime * 6));
if (_buffer.Count == 0) {
return;
}
float localInterpolationTime = Time.time - firstLocalTime - 2 * tickDelta;
var first = _buffer[0];
if (localInterpolationTime < first.time) {
Debug.Log(Time.frameCount + ": BeforeFirst: " + localInterpolationTime + " buffer: " + PrintBuffer(_buffer));
transform.position = first.position;
return;
}
var last = _buffer[_buffer.Count - 1];
if (localInterpolationTime > last.time) {
var lastDelta = (float) (localInterpolationTime - last.time);
if (lastDelta > tickDelta) {
last.time += Mathf.FloorToInt(lastDelta / tickDelta) * tickDelta;
_buffer[_buffer.Count - 1] = last;
}
_buffer.RemoveRange(0, _buffer.Count - 1);
Debug.Log(Time.frameCount + ": AfterLast: " + localInterpolationTime + " buffer: " + PrintBuffer(_buffer));
transform.position = last.position;
return;
}
int i = _buffer.Count - 1;
while (i > 0 && _buffer[i].time > localInterpolationTime) {
i--;
}
var left = _buffer[i];
var right = _buffer[i + 1];
transform.position = Vector3.Lerp(left.position, right.position, (localInterpolationTime - left.time) / (right.time - left.time));
//Debug.Log(Time.frameCount + ": Interpolaiton: " + localInterpolationTime + " index: " + i + " buffer: " + PrintBuffer(_buffer));
if (i > 0) {
_buffer.RemoveRange(0, i - 1);
}
}
I studied the principle of interpolation for more than a month spent studying only this module but could not achieve a good result
It ("OnPhotonSerializeView") transmits 10 positions instead of 60 positions per second.
the game is a 3d arena,
where the two teams play against each other what's the matter if the lags start when 3 players play ?!
and it is necessary that there were 6 people in one room!
what am I doing wrong?
//*** interpolation property ***
private Vector3 oldCorrectPos;
private Quaternion latestCorrectRot;
private double firstServerTime;
private float firstLocalTime = -1;
private float tickDelta;
private List _buffer = new List(10);
private int skipFirstFramesCount;
void Start () {
if (photonView.isMine) {
//....
} else {
tickDelta = 1f / PhotonNetwork.sendRateOnSerialize;
skipFirstFramesCount = 30;
}
}
private static string PrintBuffer(List buffer)
{
var result = string.Empty;
for (int i = 0; i < buffer.Count; i++) {
result += buffer[i].time + " ";
}
return result;
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
if(stream.isWriting) {
Vector3 pos = transform.position;
Quaternion rot = transform.rotation;
stream.SendNext(pos);
stream.SendNext(rot);
stream.SendNext(anim.GetBool ("IsMove"));
stream.SendNext(anim.GetBool ("IsAttack"));
} else {
var position = (Vector3)stream.ReceiveNext();
var rotation = (Quaternion)stream.ReceiveNext();
anim.SetBool ("IsMove", (bool)stream.ReceiveNext ());
anim.SetBool ("IsAttack", (bool)stream.ReceiveNext ());
if (skipFirstFramesCount > 0) {
skipFirstFramesCount--;
return;
}
if (firstLocalTime == -1) {
firstServerTime = info.timestamp;
firstLocalTime = Time.time;
Debug.Log(Time.frameCount + ": delta: " + (PhotonNetwork.time - info.timestamp));
}
Debug.Log(Time.frameCount + ": Server Time: " + (float) (info.timestamp - firstServerTime));
_buffer.Add(
new TimedPosition {
time = (float) (info.timestamp - firstServerTime),
position = position
}
);
latestCorrectRot = rotation;
}
}
void Update () {
if (photonView.isMine) { // if this object is under our control, we don't need to apply received position-updates
return;
}
if (skipFirstFramesCount > 0) {
return;
}
transform.rotation = Quaternion.Lerp(transform.rotation, latestCorrectRot, (Time.deltaTime * 6));
if (_buffer.Count == 0) {
return;
}
float localInterpolationTime = Time.time - firstLocalTime - 2 * tickDelta;
var first = _buffer[0];
if (localInterpolationTime < first.time) {
Debug.Log(Time.frameCount + ": BeforeFirst: " + localInterpolationTime + " buffer: " + PrintBuffer(_buffer));
transform.position = first.position;
return;
}
var last = _buffer[_buffer.Count - 1];
if (localInterpolationTime > last.time) {
var lastDelta = (float) (localInterpolationTime - last.time);
if (lastDelta > tickDelta) {
last.time += Mathf.FloorToInt(lastDelta / tickDelta) * tickDelta;
_buffer[_buffer.Count - 1] = last;
}
_buffer.RemoveRange(0, _buffer.Count - 1);
Debug.Log(Time.frameCount + ": AfterLast: " + localInterpolationTime + " buffer: " + PrintBuffer(_buffer));
transform.position = last.position;
return;
}
int i = _buffer.Count - 1;
while (i > 0 && _buffer[i].time > localInterpolationTime) {
i--;
}
var left = _buffer[i];
var right = _buffer[i + 1];
transform.position = Vector3.Lerp(left.position, right.position, (localInterpolationTime - left.time) / (right.time - left.time));
//Debug.Log(Time.frameCount + ": Interpolaiton: " + localInterpolationTime + " index: " + i + " buffer: " + PrintBuffer(_buffer));
if (i > 0) {
_buffer.RemoveRange(0, i - 1);
}
}
0