Compensación de retraso PUN 2

En Photon Network, la sincronización del reproductor se realiza mediante el envío de valores a través de la red en forma de paquetes.

Por ejemplo, para sincronizar la posición del jugador, necesitamos enviar Vector3 para la posición y Quaternion para la rotación, luego, cuando se reciben los valores, los aplicamos para transformar.

Sin embargo, dado que los valores se envían en intervalos, simplemente aplicarlos para transformar dará como resultado un movimiento entrecortado, ahí es donde entran Vector3.Lerp y Quaternion.Lerp.

transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);

Pero incluso este método tiene algunas desventajas: simplemente suavizar la posición y la rotación dará como resultado una representación inexacta del movimiento del jugador, lo que no es muy adecuado para algunos tipos de juegos, donde la precisión es importante.

A continuación se muestra una versión mejorada de la sincronización de posición, que tiene en cuenta el tiempo de red e intenta replicar el movimiento original lo más cerca posible:

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));
        }
    }
}
  • Adjunte el script anterior a su instancia de Player y asígnelo a PhotonView Observed Components.
Artículos sugeridos
Crea un juego de coches multijugador con PUN 2
Unity agrega chat multijugador a PUN 2 Rooms
Sincronizar cuerpos rígidos a través de la red usando PUN 2
Crea un juego multijugador en Unity usando PUN 2
Guía para principiantes de Photon Network (clásico)
Creación de juegos multijugador en red en Unity
Compresión de datos multijugador y manipulación de bits