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.
Articoli suggeriti
Realizza un gioco di auto multiplayer con PUN 2
Unity Aggiunta della chat multigiocatore alle stanze di PUN 2
Sincronizza i corpi rigidi sulla rete usando PUN 2
Crea un gioco multiplayer in Unity usando PUN 2
Photon Network (Classic) Guida per principianti
Creazione di giochi in rete multiplayer in Unity
Compressione dei dati multigiocatore e manipolazione dei bit