PUN 2 Lagkompensation
I Photon Network udføres spillersynkronisering ved at sende værdier over netværket i form af pakker.
For eksempel, for at synkronisere spillerposition, skal vi sende Vector3 til position og Quaternion til rotation, og når værdierne er modtaget, anvender vi dem til at transformere.
Men da værdierne sendes i intervaller, vil blot at anvende dem til transformation resultere i en hakkende bevægelse, det er her Vector3.Lerp og Quaternion.Lerp kommer på plads.
transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
Men selv denne metode har nogle ulemper: blot udjævning af position og rotation vil resultere i en unøjagtig repræsentation af spillerens bevægelse, hvilket ikke er helt egnet til nogle typer spil, hvor præcision er vigtig.
Nedenfor er en forbedret version af positionssynkronisering, som tager højde for netværkstid og forsøger at replikere den oprindelige bevægelse så tæt som muligt:
using UnityEngine;
using Photon.Pun;
public class PUN2_LagFreePlayerSync : MonoBehaviourPun, IPunObservable
{
//Values that will be synced over network
Vector3 latestPos;
Quaternion latestRot;
//Lag compensation
float currentTime = 0;
double currentPacketTime = 0;
double lastPacketTime = 0;
Vector3 positionAtLastPacket = Vector3.zero;
Quaternion rotationAtLastPacket = Quaternion.identity;
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
//We own this player: send the others our data
stream.SendNext(transform.position);
stream.SendNext(transform.rotation);
}
else
{
//Network player, receive data
latestPos = (Vector3)stream.ReceiveNext();
latestRot = (Quaternion)stream.ReceiveNext();
//Lag compensation
currentTime = 0.0f;
lastPacketTime = currentPacketTime;
currentPacketTime = info.SentServerTime;
positionAtLastPacket = transform.position;
rotationAtLastPacket = transform.rotation;
}
}
// Update is called once per frame
void Update()
{
if (!photonView.IsMine)
{
//Lag compensation
double timeToReachGoal = currentPacketTime - lastPacketTime;
currentTime += Time.deltaTime;
//Update remote player
transform.position = Vector3.Lerp(positionAtLastPacket, latestPos, (float)(currentTime / timeToReachGoal));
transform.rotation = Quaternion.Lerp(rotationAtLastPacket, latestRot, (float)(currentTime / timeToReachGoal));
}
}
}
- Vedhæft scriptet ovenfor til din afspillerinstans og tildel det til PhotonView Observed Components.