Unity UNet проблема со связью: интервал прибытия сообщения не согласован и пакетное прибытие

Я построил очень простую низкоуровневую передачу сообщений UNet (LLAPI) между клиентом и сервером, где я отправляю только Vector3 с сервера на клиент. И серверное, и клиентское приложение работают на одном компьютере. Запуск Windows 10 и Unity 2018.2.15f1.

Я пытался отправлять сообщения каждый цикл обновления (средний интервал передачи 16 мс), и на клиенте я замечаю, что от 40% до 50% полученных сообщений приходят в один и тот же момент времени (т. Е. Вы получаете пакетное поступление сообщений как 2 или более сообщения приходят в одно и то же время). Чтобы измерить это, я установил секундомер, который проверяет прошедшее время между приходом сообщений. Секундомер реализован внутри обратного вызова при приеме сообщения. Это довольно проблематично, так как если вы обновляете позу объекта и два сообщения позы приходят одновременно, то только последнее сообщение используется для обновления позы объекта.

Затем я попытался отправлять сообщения каждый второй цикл обновления (средний интервал передачи 33 мс). В этом случае на клиенте нет сообщений, поступающих одновременно, но 20% сообщений поступают с интервалом, превышающим 36 мс.

Кто-нибудь тоже сталкивался с этой проблемой? Есть ли рекомендуемое решение этой проблемы? Моя цель - отправлять сообщения с частотой 60 Гц и получать их с одинаковой скоростью без большой задержки.

В случае, если кто-то захочет попробовать код, вот сценарии сервера и клиента.

Это сервер:

using UnityEngine.Networking;

public class ServerScript : MonoBehaviour
{
private const short ClientToServerMsgIdHaptic = 3007;
public bool isAtStartup = true;

private System.Diagnostics.Stopwatch stopWatch;
private double lastTimeStamp;
private double currentTimeStamp;

private float pktCounter0 = 0;
private float pktCounterHighDelay = 0;
private float pktCounterHighDelayX = 0;

private float pktCountertotal = 0;
private double avgtime = 0;
private double avgtimeAcc = 0;

public class ClientToServerMessage : MessageBase
{
    public Vector3 posObj;
}

void Update()
{
    if (isAtStartup)
    {
        SetupServer();
        Debug.Log("Server is running");
    }

    // print the avg arrival time after 1000 packets are received
    if(pktCountertotal == 1000)
    {
        avgtime = avgtimeAcc / pktCountertotal;
        Debug.Log("Average time " + avgtime);
    }
}

// Create a client and connect to the server port
public void SetupServer()
{
    NetworkServer.RegisterHandler(ClientToServerMsgIdHaptic, OnCommandReceive);
    NetworkServer.Listen(4444);
    isAtStartup = false;
    Debug.Log("Server has started");

    stopWatch = new System.Diagnostics.Stopwatch();
    stopWatch.Start();
    lastTimeStamp = 0;
    pktCounterHighDelay = 0;
}

public void OnCommandReceive(NetworkMessage netMsg)
{
    ClientToServerMessage Message = netMsg.ReadMessage<ClientToServerMessage>();
    transform.position = Message.posObj;

    currentTimeStamp = stopWatch.ElapsedMilliseconds - lastTimeStamp;
    lastTimeStamp = stopWatch.ElapsedMilliseconds;

    // burst arrival
    if (currentTimeStamp <= 2)
    {
        pktCounter0 = pktCounter0 + 1;
    }
    // delay larger than 36
    if (currentTimeStamp > 36)
    {
        pktCounterHighDelay++;
    }
    // delay larger than 51
    if (currentTimeStamp > 51)
    {
        pktCounterHighDelayX++;
    }
    pktCountertotal = pktCountertotal + 1;
    avgtimeAcc = avgtimeAcc + currentTimeStamp;
    Debug.Log("Time between received messages" + currentTimeStamp.ToString("F2") + " pkttotal0 " + pktCounter0 + " pktotal " + pktCountertotal + " pkts high delay " + pktCounterHighDelay + " pkts high delay X " + pktCounterHighDelayX);

}

}

А вот и клиент

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;

public class ClientScript : MonoBehaviour {

// Definitions
NetworkClient myClient;
private bool isAtStartup = true;
private const short ClientToServerMsgId = 3007;
private bool isConnected = false;
private float counter = 0;
private System.Diagnostics.Stopwatch stopWatch;
private double lastTimeStamp;
private double currentTimeStamp;

public class ClientToServerMessage : MessageBase
{
    public Vector3 posObj;
}

// Create a client and connect to the server port
public void SetupClient()
{
    myClient = new NetworkClient();
    myClient.RegisterHandler(MsgType.Connect, OnConnected);
    myClient.Connect("YOUR IP ADDRESS", 4444);
    isAtStartup = false;
    Debug.Log("Setting up client");

    stopWatch = new System.Diagnostics.Stopwatch();
    stopWatch.Start();
    lastTimeStamp = 0;
}
// Use this for initialization
void Start () {
    if (isAtStartup) // if at startup start the client
    {
        SetupClient();
    }
}

// Update is called once per frame
void Update () {

    var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
    var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

    transform.Rotate(0, x, 0);
    transform.Translate(0, 0, z);

    if (isConnected)
    {
        // to send every update loop: counter = 0
        // to send every second update loop: counter = 1
        if (counter == 0)
        {
            ClientToServerMessage msg = new ClientToServerMessage();
            msg.posObj = transform.position;
            currentTimeStamp = stopWatch.ElapsedMilliseconds - lastTimeStamp;
            lastTimeStamp = stopWatch.ElapsedMilliseconds;
            Debug.Log("Time between transmitted messages" + currentTimeStamp.ToString("F2"));

            myClient.Send(ClientToServerMsgId, msg);
            counter = -1;
        }
        counter = counter + 1;
    }
}

// Create Connected successfull flag
public void OnConnected(NetworkMessage netMsg)
{
    Debug.Log("Connected to server");
    isConnected = true;
}

}

0 ответов

Другие вопросы по тегам