PUN 2 지연 보상

Photon Network에서 플레이어 동기화는 패킷 형태로 네트워크를 통해 값을 전송하여 수행됩니다.

예를 들어 플레이어 위치를 동기화하려면 위치에 대해 Vector3를 보내고 회전에 대해 Quaternion을 전송해야 합니다. 그런 다음 값이 수신되면 이를 변환에 적용합니다.

그러나 값이 간격을 두고 전송되기 때문에 단순히 변환에 적용하면 고르지 못한 움직임이 발생하게 되며, 여기서 Vector3.Lerp 및 Quaternion.Lerp가 사용됩니다.

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

그러나 이 방법에도 몇 가지 단점이 있습니다. 단순히 위치와 회전을 부드럽게 하면 플레이어의 움직임이 부정확하게 표현되므로 정밀도가 중요한 일부 게임 유형에는 적합하지 않습니다.

다음은 네트워킹 시간을 고려하고 원래 움직임을 최대한 가깝게 복제하려고 시도하는 향상된 위치 동기화 버전입니다.

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));
        }
    }
}
추천 기사
PUN 2로 멀티플레이어 자동차 게임 만들기
Unity, PUN 2 룸에 멀티플레이어 채팅 추가
PUN 2를 사용하여 네트워크를 통해 강체 동기화
PUN 2를 사용하여 Unity에서 멀티플레이어 게임 만들기
Photon 네트워크(클래식) 초보자 가이드
Unity에서 멀티플레이어 네트워크 게임 구축
멀티플레이어 데이터 압축 및 비트 조작