我在客户端和服务器之间构建了一个非常简单的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;
}
}