Синхронизация соперника по сети. Лаги/рывки/дергания

Сеть в Unity3D

Re: Синхронизация соперника по сети. Лаги/рывки/дергания

Сообщение Aleksey 28 май 2017, 16:35

откуда вообще берется интерполяция позиции?

Выжимка из моей документации -

transform.position = Vector3.Lerp(A, B, fraction);
Если нам нужно пройти путь от точки А до точки Б в размере 10 точек то надо fraction = 1/10 =0.1f
fraction = fraction + 0.1f;
transform.position = Vector3.Lerp(new Vector2(0,0), new Vector2(5, 5), fraction);
transform.position от нуля передвигается в 0.5f,0.5f - 1,1 – 1.5f,1.5f…..5,5. Десятая доля отрезка в размере пяти единиц равна 0.5f.(получаем путь из десяти точек между двумя точками(0,0 и 5,5))
Теперь объясню зачем нам рисовать точки движения между двумя точками:
Есть проблема в передачи движения по сети. Стабильная игра = 60 фпс. Это значит 60 точек позиций в секунду. Мы не можем передавать 60 позиций через сеть. Это очень больше затраты передачи трафика в секунду. Для экономии трафика по дефолту передают 10 позиций в секунду. OnPhotonSerializeView вызывается 10 раз в секунду. Если будем передавать движение 10 позиций в секунду .Получаем паузу между этими позициями которая равна шести кадрам(60/10). Эти отрезки между позициями в размере времени шести кадров должны сглаживаться. С помощью интерполяции мы создаем новые точки позиций в этом отрезке. Нужно создать минимум шесть точек. Нам нужно брать 1/6 долю отрезка. Это примерно Time.deltaTime * 10 . Почему разработчики фотона взяли Time.deltaTime * 9 ? Мы не должны никогда полностью догонять конец отрезка лерпа ,тогда в этом случае мы будем стоять 1-2 кадра в конце отрезка лерпа ожидая новую позицию по сети. И поэтому желательней двигаться медленней Time.deltaTime * 10.

Всегда должна быть только экстрополяция

Нет. и это подтверждает например случай который показан здесь. Тут проблема которая часто возникает, когда пытаются в быструю интерполяцию(путь от точки А до точки Б передвигается очень быстро(рисуется очень мало точек в отрезке лерпа)) добавить не медленную экстраполяцию. В итоге она обгоняет отрезки которые рисует интерполяция.

Хотя если автор поста уравновесит экстраполяцию то я полностью поменяю свою риторику)) и пересмотрю многое)). Но пока на видео я вижу другое.

Вот собственно пример быстрой интерполяции от разработчиков фотон клауда
Синтаксис:
Используется csharp
using UnityEngine;
[RequireComponent(typeof (PhotonView))]
public class CubeLerp : Photon.MonoBehaviour, IPunObservable
{
    private Vector3 latestCorrectPos;
    private Vector3 onUpdatePos;
    private float fraction;

    public void Start()
    {
        latestCorrectPos = transform.position;
        onUpdatePos = transform.position;
    }

    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting)
            stream.SendNext(transform.position);
        else
        {
            Vector3 pos = Vector3.zero;
            pos = (Vector3)stream.ReceiveNext();

            latestCorrectPos = pos;              
            onUpdatePos = transform.position;
            fraction = 0;                          
        }
    }

    public void Update()
    {
        if (photonView.isMine)  return;
               
        fraction = fraction + Time.deltaTime * 9;
        transform.position = Vector3.Lerp(onUpdatePos, latestCorrectPos, fraction);
    }
}

Если мы в этот пример добавим велосити в районе 10 единиц и выше то получаем примерно предсказание потому что изменение направления велосити у нас же будет с задержкой в районе шести кадров
-----
про скрипт в начале поста:
Даже при том что у него в скрипте якобы отделен лерп от велосити
у него иф - лерп, елсе - трансформ позишин + велосити. Все равно когда он переходит в елсе у него иф лерп до конца отрезка то не дошел и получается мешанина из двух движений - Лерпа и добавления велосити и это все очень не просто нормализовать без обгонов.

По поводу задержки в шесть кадров это я говорю про фотонклауд) хотя сомневаюсь что в Unet позиции передаются по сети 60 раз в секунду)) наверно тоже 10 примерно
Продукты на тему онлайна в Ассет Сторе
_https://www.assetstore.unity3d.com/en/# ... sher:21589
Аватара пользователя
Aleksey
UNIт
 
Сообщения: 56
Зарегистрирован: 17 фев 2015, 16:09

Re: Синхронизация соперника по сети. Лаги/рывки/дергания

Сообщение Tolking 28 май 2017, 17:11

Еще раз... Мы ВСЕГДА получаем пакеты с запаздыванием. Всегда без исключения. Как можно получить ТЕКУЩЕЕ положение из прошлого интерполяцией? Какие "позиции в этом отрезке" нет никакого отрезка есть экстраполированное положение и текущее положение... Вот переходить из текущего в экстраполированное можно либо скачком либо интерполяцией, причем делать это можно даже не учитывая время просто Lerp(A, B, 0.5) например.

1) Синхронизировать время.
2) Передавать - время отправки, позицию, скорость
3) Экстраполировать ПОЗИЦИЮ исходя из присланной позиции, прошедшего времени с момента ОТПРАВКИ и новой скорости.
4) Каждый кадр менять ПОЗИЦИЮ с последней полученной скоростью, и интерполировать положение ОТОБРАЖЕНИЯ к экстраполированной позиции.
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2715
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Пред.

Вернуться в Сеть

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


cron