При разработке игр на Unity Photon Unity Networking (PUN) — это популярная платформа для реализации многопользовательских функций. Однако одна из распространенных проблем, возникающих при использовании представления сетевого преобразования PUN 2, — это тряское перемещение сетевых объектов. В этой статье мы рассмотрим несколько способов сгладить это нервное движение и предоставим примеры кода для демонстрации каждого подхода.
Методы сглаживания нервных движений:
- Интерполяция.
Интерполяция – это метод, который сглаживает движение путем постепенного перехода от предыдущей позиции к текущей позиции. В PUN 2 вы можете включить интерполяцию для компонента Network Transform View, настроив параметр «Интерполировать движение». Вот пример фрагмента кода:
using UnityEngine;
using Photon.Pun;
public class SmoothMovement : MonoBehaviourPun, IPunObservable
{
private Vector3 networkPosition;
private Quaternion networkRotation;
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
stream.SendNext(transform.position);
stream.SendNext(transform.rotation);
}
else
{
networkPosition = (Vector3)stream.ReceiveNext();
networkRotation = (Quaternion)stream.ReceiveNext();
}
}
private void Update()
{
if (!photonView.IsMine)
{
transform.position = Vector3.Lerp(transform.position, networkPosition, Time.deltaTime * 10);
transform.rotation = Quaternion.Lerp(transform.rotation, networkRotation, Time.deltaTime * 10);
}
}
}
- Экстраполяция.
Экстраполяция прогнозирует будущее положение сетевого объекта на основе его предыдущих положений. Оценив следующую позицию, можно сгладить движение дальше. Вот пример фрагмента кода:
private void Update()
{
if (!photonView.IsMine)
{
transform.position += (networkPosition - transform.position) * 0.1f;
transform.rotation = Quaternion.Slerp(transform.rotation, networkRotation, Time.deltaTime * 10);
}
}
- Компенсация задержки.
Компенсация задержки помогает устранить проблемы с задержкой за счет учета задержки между отправкой и получением данных. Применяя разницу во времени к обновлениям положения и вращения, вы можете добиться более плавного движения. Вот пример фрагмента кода:
private void Update()
{
if (!photonView.IsMine)
{
float lag = Mathf.Abs((float)(PhotonNetwork.Time - info.SentServerTime));
Vector3 extrapolatedPosition = networkPosition + (transform.forward * info.GetRoundTripTime() * 0.001f);
transform.position = Vector3.Lerp(transform.position, extrapolatedPosition, lag);
transform.rotation = Quaternion.Slerp(transform.rotation, networkRotation, lag);
}
}
- Алгоритм сглаживания.
Реализация собственного алгоритма сглаживания может обеспечить больший контроль над поведением движения. Одним из распространенных подходов является использование средневзвешенного значения предыдущих позиций и скоростей для расчета сглаженной позиции. Вот пример фрагмента кода:
private void Update()
{
if (!photonView.IsMine)
{
float smoothingFactor = 0.9f;
transform.position = Vector3.Lerp(transform.position, networkPosition, smoothingFactor);
transform.rotation = Quaternion.Slerp(transform.rotation, networkRotation, smoothingFactor);
}
}