PUN 2 Lagkompensasjon
I Photon Network gjøres spillersynkronisering ved å sende verdier over nettverket i form av pakker.
For å synkronisere spillerposisjonen må vi for eksempel sende Vector3 for posisjon og Quaternion for rotasjon, og når verdiene er mottatt, bruker vi dem for å transformere.
Men siden verdiene sendes i intervaller, vil bare å bruke dem til å transformere resultere i en hakkete bevegelse, det er der Vector3.Lerp og Quaternion.Lerp kommer på plass.
transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
Men selv denne metoden har noen ulemper: bare å jevne ut posisjon og rotasjon vil resultere i en unøyaktig representasjon av spillerens bevegelse, noe som ikke er helt egnet for noen typer spill, hvor presisjon er viktig.
Nedenfor er en forbedret versjon av posisjonssynkronisering, som tar hensyn til nettverkstid og prøver å gjenskape den opprinnelige bevegelsen så tett som mulig:
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));
}
}
}
- Fest skriptet ovenfor til din spillerforekomst og tilordne det til PhotonView Observed Components.