PUN 2 Verzögerungskompensation

In Photon Network erfolgt die Player-Synchronisierung durch das Senden von Werten über das Netzwerk in Form von Paketen.

Um beispielsweise die Spielerposition zu synchronisieren, müssen wir Vector3 für die Position und Quaternion für die Rotation senden. Wenn die Werte dann empfangen werden, wenden wir sie zur Transformation an.

Da die Werte jedoch in Intervallen gesendet werden, führt die einfache Anwendung auf die Transformation zu einer abgehackten Bewegung. Hier kommen Vector3.Lerp und Quaternion.Lerp ins Spiel.

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

Aber auch diese Methode hat einige Nachteile: Das bloße Glätten von Position und Drehung führt zu einer ungenauen Darstellung der Bewegung des Spielers, was für einige Arten von Spielen, bei denen es auf Präzision ankommt, nicht ganz geeignet ist.

Nachfolgend finden Sie eine verbesserte Version der Positionssynchronisierung, die die Netzwerkzeit berücksichtigt und versucht, die ursprüngliche Bewegung so genau wie möglich nachzubilden:

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));
        }
    }
}
  • Hängen Sie das obige Skript an Ihre Player-Instanz an und weisen Sie es PhotonView Observed Components zu.
Empfohlene Artikel
Erstellen Sie ein Multiplayer-Autospiel mit PUN 2
Unity fügt Multiplayer-Chat zu den PUN 2-Räumen hinzu
Synchronisieren Sie Rigidbodies über das Netzwerk mit PUN 2
Erstellen Sie mit PUN 2 ein Multiplayer-Spiel in Unity
Erstellen vernetzter Multiplayer-Spiele in Unity
Multiplayer-Datenkomprimierung und Bitmanipulation
Unity Online-Ranglisten-Tutorial