PUN 2 Compensazione ritardo
In Photon Network, la sincronizzazione del player viene eseguita inviando valori sulla rete sotto forma di pacchetti.
Ad esempio, per sincronizzare la posizione del giocatore dobbiamo inviare Vector3 per la posizione e Quaternion per la rotazione, quindi quando i valori vengono ricevuti, li applichiamo per trasformare.
Tuttavia, poiché i valori vengono inviati a intervalli, la loro semplice applicazione per la trasformazione risulterà in un movimento discontinuo, è qui che entrano in gioco Vector3.Lerp e Quaternion.Lerp.
transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
Ma anche questo metodo presenta alcuni svantaggi: il semplice livellamento della posizione e della rotazione si tradurrà in una rappresentazione imprecisa del movimento del giocatore, che non è del tutto adatta per alcuni tipi di giochi, in cui la precisione è importante.
Di seguito è riportata una versione migliorata della sincronizzazione della posizione, che tiene conto del tempo di rete e cerca di replicare il movimento originale il più fedelmente possibile:
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));
}
}
}
- Allega lo script precedente alla tua istanza Player e assegnalo a PhotonView Observed Components.