Unity UNet通信问题:消息到达间隔不一致并且突发到达

时间:2018-11-22 08:14:53

标签: unity3d unity3d-unet

我在客户端和服务器之间构建了一个非常简单的UNet低级消息传输(LLAPI),在其中我仅将Vector3从服务器发送到客户端。服务器和客户端应用程序都在同一台计算机上运行。运行Windows 10和Unity 2018.2.15f1。

我尝试在每个更新循环(平均传输间隔16毫秒)发送消息,并且在客户端,我注意到有40%到50%的接收消息恰好在同一时间到达(即,突发到达)中的2条或2条以上消息在同一准确时间到达)。为了测量这一点,我安装了一个秒表来检查消息到达之间的经过时间。秒表在消息接收回调内部实现。这是很成问题的,因为如果您要更新对象的姿态并且两个姿态消息同时到达,那么仅使用最后一条消息来更新对象的姿态。

然后我尝试每隔第二个更新循环(平均传输间隔33毫秒)发送消息。在这种情况下,在客户端没有同时到达的消息,但是有20%的消息以大于36毫秒的间隔到达。

有人也遇到过这个问题吗?是否有针对此问题的建议解决方法?我的目标是以60 Hz的速率发送消息,并以相同的速率接收消息,而不会造成很大的延迟。

万一有人想尝试代码,这里是服务器和客户端脚本。

这是服务器:

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 个答案:

没有答案