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));
}
}
}
- צרף את הסקריפט שלמעלה למופע הנגן שלך והקצה אותו לרכיבי PhotonView Observed.