PUN 2 Compensare lag

În Photon Network, sincronizarea jucătorilor se face prin trimiterea de valori prin rețea sub formă de pachete.

De exemplu, pentru a sincroniza poziția jucătorului trebuie să trimitem Vector3 pentru poziție și Quaternion pentru rotație, apoi când valorile sunt primite, le aplicăm pentru a transforma.

Cu toate acestea, deoarece valorile sunt trimise la intervale, pur și simplu aplicarea lor pentru a transforma va avea ca rezultat o mișcare agitată, aici intervin Vector3.Lerp și Quaternion.Lerp.

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

Dar chiar și această metodă are unele dezavantaje: simpla netezire a poziției și rotației va avea ca rezultat o reprezentare inexactă a mișcării jucătorului, ceea ce nu este tocmai potrivit pentru unele tipuri de jocuri, unde precizia este importantă.

Mai jos este o versiune îmbunătățită a sincronizării poziției, care ia în considerare timpul de conectare în rețea și încearcă să reproducă cât mai aproape posibil mișcarea originală:

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));
        }
    }
}
  • Atașați scriptul de mai sus la instanța dvs. Player și atribuiți-l la PhotonView Observed Components.
Articole sugerate
Creați un joc cu mașini multiplayer cu PUN 2
Unity Adăugând chat multiplayer în camerele PUN 2
Sincronizați corpuri rigide prin rețea folosind PUN 2
Faceți un joc multiplayer în Unity folosind PUN 2
Photon Network (Clasic) Ghid pentru începători
Crearea de jocuri multiplayer în rețea în Unity
Comprimarea datelor multiplayer și manipularea biților