Unity UNet communication problem: message arrival interval not consistent and burst arrival
up vote
0
down vote
favorite
I built a very simple UNet low level message transmission (LLAPI) between a client and a server, where I send just a Vector3 from the server to client. Both server and client application are running in the same machine. Running Windows 10 and Unity 2018.2.15f1.
I tried sending the messages every update loop (avg transmission interval 16 ms), and at the client I notice that between 40% and 50% of the received messages arrive at the exact same time instant (i.e. you have a burst arrival of the messages as 2 or more messages arrive at the same exact time). To measure this I setup a stopwatch which checks the elapsed time between message arrivals. The stopwatch is implemented inside the message reception callback. This is quite problematic since if you are updating a pose of an object and two pose messages arrive at the same time, then only the last message is used to update the object pose.
I then tried sending the messages every second update loop (avg transmission interval 33 ms). In this case, at the client there are no messages arriving at the same time, but 20% of the messages arrive with an interval that is larger than 36 ms.
Has anyone experienced this problem as well? Is there any recommended workaround to this issue? My goal is to send messages at a rate of 60 Hz and receive them at the same rate without a large delay.
In case anyone wants to try the code, here is the Server and Client scripts.
This is the server:
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);
}
}
And here is the client
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;
}
}
unity3d unity3d-unet
add a comment |
up vote
0
down vote
favorite
I built a very simple UNet low level message transmission (LLAPI) between a client and a server, where I send just a Vector3 from the server to client. Both server and client application are running in the same machine. Running Windows 10 and Unity 2018.2.15f1.
I tried sending the messages every update loop (avg transmission interval 16 ms), and at the client I notice that between 40% and 50% of the received messages arrive at the exact same time instant (i.e. you have a burst arrival of the messages as 2 or more messages arrive at the same exact time). To measure this I setup a stopwatch which checks the elapsed time between message arrivals. The stopwatch is implemented inside the message reception callback. This is quite problematic since if you are updating a pose of an object and two pose messages arrive at the same time, then only the last message is used to update the object pose.
I then tried sending the messages every second update loop (avg transmission interval 33 ms). In this case, at the client there are no messages arriving at the same time, but 20% of the messages arrive with an interval that is larger than 36 ms.
Has anyone experienced this problem as well? Is there any recommended workaround to this issue? My goal is to send messages at a rate of 60 Hz and receive them at the same rate without a large delay.
In case anyone wants to try the code, here is the Server and Client scripts.
This is the server:
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);
}
}
And here is the client
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;
}
}
unity3d unity3d-unet
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I built a very simple UNet low level message transmission (LLAPI) between a client and a server, where I send just a Vector3 from the server to client. Both server and client application are running in the same machine. Running Windows 10 and Unity 2018.2.15f1.
I tried sending the messages every update loop (avg transmission interval 16 ms), and at the client I notice that between 40% and 50% of the received messages arrive at the exact same time instant (i.e. you have a burst arrival of the messages as 2 or more messages arrive at the same exact time). To measure this I setup a stopwatch which checks the elapsed time between message arrivals. The stopwatch is implemented inside the message reception callback. This is quite problematic since if you are updating a pose of an object and two pose messages arrive at the same time, then only the last message is used to update the object pose.
I then tried sending the messages every second update loop (avg transmission interval 33 ms). In this case, at the client there are no messages arriving at the same time, but 20% of the messages arrive with an interval that is larger than 36 ms.
Has anyone experienced this problem as well? Is there any recommended workaround to this issue? My goal is to send messages at a rate of 60 Hz and receive them at the same rate without a large delay.
In case anyone wants to try the code, here is the Server and Client scripts.
This is the server:
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);
}
}
And here is the client
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;
}
}
unity3d unity3d-unet
I built a very simple UNet low level message transmission (LLAPI) between a client and a server, where I send just a Vector3 from the server to client. Both server and client application are running in the same machine. Running Windows 10 and Unity 2018.2.15f1.
I tried sending the messages every update loop (avg transmission interval 16 ms), and at the client I notice that between 40% and 50% of the received messages arrive at the exact same time instant (i.e. you have a burst arrival of the messages as 2 or more messages arrive at the same exact time). To measure this I setup a stopwatch which checks the elapsed time between message arrivals. The stopwatch is implemented inside the message reception callback. This is quite problematic since if you are updating a pose of an object and two pose messages arrive at the same time, then only the last message is used to update the object pose.
I then tried sending the messages every second update loop (avg transmission interval 33 ms). In this case, at the client there are no messages arriving at the same time, but 20% of the messages arrive with an interval that is larger than 36 ms.
Has anyone experienced this problem as well? Is there any recommended workaround to this issue? My goal is to send messages at a rate of 60 Hz and receive them at the same rate without a large delay.
In case anyone wants to try the code, here is the Server and Client scripts.
This is the server:
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);
}
}
And here is the client
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;
}
}
unity3d unity3d-unet
unity3d unity3d-unet
edited Nov 22 at 8:30
asked Nov 22 at 8:14
jaraujo
1887
1887
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53426472%2funity-unet-communication-problem-message-arrival-interval-not-consistent-and-bu%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown