PUN 2 vertragingscompensatie
In Photon Network wordt spelersynchronisatie uitgevoerd door waarden via het netwerk te verzenden in de vorm van pakketten.
Om bijvoorbeeld de positie van de speler te synchroniseren, moeten we Vector3 voor positie en Quaternion voor rotatie sturen. Wanneer de waarden worden ontvangen, passen we deze toe om te transformeren.
Omdat de waarden echter in intervallen worden verzonden, zal het simpelweg toepassen ervan op transformatie resulteren in een schokkerige beweging, en dat is waar Vector3.Lerp en Quaternion.Lerp op hun plaats komen.
transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
Maar zelfs deze methode heeft enkele nadelen: het simpelweg gladstrijken van positie en rotatie zal resulteren in een onnauwkeurige weergave van de beweging van de speler, wat niet helemaal geschikt is voor sommige soorten spellen, waarbij precisie belangrijk is.
Hieronder vindt u een verbeterde versie van positiesynchronisatie, die rekening houdt met netwerktijd en probeert de oorspronkelijke beweging zo goed mogelijk te repliceren:
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));
}
}
}
- Voeg het bovenstaande script toe aan uw Player-instantie en wijs het toe aan PhotonView Observed Components.