PUN 2 vertragingscompensatie

In Photon Network wordt spelersynchronisatie uitgevoerd door waarden via het netwerk te verzenden in de vorm van pakketten.

Om bijvoorbeeld de positie van de speler te synchroniseren, moeten we Vector3 voor positie en Quaternion voor rotatie sturen. Wanneer de waarden worden ontvangen, passen we deze toe om te transformeren.

Omdat de waarden echter in intervallen worden verzonden, zal het simpelweg toepassen ervan op transformatie resulteren in een schokkerige beweging, en dat is waar Vector3.Lerp en Quaternion.Lerp op hun plaats komen.

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

Maar zelfs deze methode heeft enkele nadelen: het simpelweg gladstrijken van positie en rotatie zal resulteren in een onnauwkeurige weergave van de beweging van de speler, wat niet helemaal geschikt is voor sommige soorten spellen, waarbij precisie belangrijk is.

Hieronder vindt u een verbeterde versie van positiesynchronisatie, die rekening houdt met netwerktijd en probeert de oorspronkelijke beweging zo goed mogelijk te repliceren:

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));
        }
    }
}
  • Voeg het bovenstaande script toe aan uw Player-instantie en wijs het toe aan PhotonView Observed Components.
Voorgestelde artikelen
Maak een multiplayer-autospel met PUN 2
Unity voegt multiplayer-chat toe aan de PUN 2-kamers
Synchroniseer starre lichamen via netwerk met PUN 2
Maak een multiplayergame in Unity met PUN 2
Samen multiplayer-netwerkgames bouwen
Multiplayer-datacompressie en bitmanipulatie
Unity Online Leaderboard-tutorial