Best way to send ping to clients?

I would like my clients to be able to display the other players’ pings.

My server is authorative. The current solutions I am thinking of are:

  1. Send 1 RPC call to each client every 1 second.

I don’t think this is possible to do in a sensible way, since I would have to transmit (max amount of players) ints every time, since I don’t think you can send arrays, or dynamically change the amount of parameters sent.

  1. Send (number of players) RPC calls to each client every 1 second.

Wouldn’t this have a lot of overhead to have one RPC call per player, and just be wasting bandwidth aswell?

  1. Use my current NetworkViews (serializing scripts) that I sync players coordinates with, to send the ping of each player to his corresponding NetworkView

This would be a giant waste of bandwidth, since I sync my NetworkViews far more often than ping would need to be updated.

Am I missing any good solutions? What are your thoughts?

serialize the array into a string, and send that. Then have the clients just deserialize the string back into an integer array.

How do I serialize something for sending it in an RPC call? (I assume you are not talking about networkviews since, they are called far too often)

look at :

Network.connections which is an array with connections
and Network.GetAveragePing( Network.connections[0] ) and so on

As I read the documentation, that will give me the player to player ping. I am interested in the player to server ping.

the server in Unity networking is the first player in that list

But, I am interested in letting every player know every player’s player to server ping.

by serializing, I mean by writing the array to a string. So you’d have an array of something like:

[50,45,30,57,25]

you would then literally write this out to a string:

“50,45,30,57,25”

then send that. The client will get this string, then parse it back in to an array.

You can actually compress this by converting the integers into ascii values (which means you’d first have to convert the integer values to base 128), and send that, and then do the reverse on receiving. You can look up integer to ascii conversion in google, there’s some csharp examples that you can use.

Thanks cerebrate. Based on the directions you gave me, I made this i unityscript. Now my only question is, if there is something I could do smarter?

class Serializer extends System.Object
{
    function Serialize(intArray : Array) : String
	{
		var s : String = "";
		var c : char;
		for (var x=0; x < intArray.length; x++)
		{
			c = intArray[x];
			s += c;
		}
        return s;
    }
	function UnSerialize(arrayString : String) : Array
	{
        var a : Array = new Array();
		var i : int;
		for (var x=0; x < arrayString.length; x++)
		{
			i = arrayString[x];
			a.Push(i);
		}
        return a;
    }
}

Does that actually work? Interesting if it does. The problem I see is that you’re only giving a character for each integer in the array. This is probably going to result in:

pings only up to 127 (if it’s converting them how I think it is), and pings over 127 are just going to start back at 0 and work their way up again

You can fix this by saying each integer is probably not going to go over 16383 (gotta include 0), and just specify that each array value is specified in 2 characters (as a number range of 16384 results in only two characters required for conversion to base 128), rather than 1, as 1 character limits you to a ping range of 0-127, while 2 characters increases this to 0-16383.

to do this you have to do something like:

ping = Mathf.Clamp(ping, 0, 16383);
var pingChar1 : int = ping /128; //(don't use floats, you don't want the decimal value, nor do you want to round it)
if (ping >= 128) var pingChar2 : int = ping % 128; //this gives you the second place value
else pingChar2 = 0;
var c1 : char = pingChar1;
var c2 : char = pingChar2;
s+= c2;
s+= c1;

for deserializing, you want to do the reverse:

var i : int;
var j : int;
for (var x=0; x < arraySTring.length-1;x+=2){
i = arrayString[x];
j = arrayString[x+1];
var actualVal : int = (i * 128) + j
}

The code below prints this: (So I’d say its working pretty well)

function Serialize(intArray : Array) : String
{
	var s : String = "";
	var c : char;
	for (var x=0; x < intArray.length; x++)
	{
		c = intArray[x];
		s += c;
	}
	return s;
}

function UnSerialize(arrayString : String) : Array
{
	var a : Array = new Array();
	var i : int;
	for (var x=0; x < arrayString.length; x++)
	{
		i = arrayString[x];
		a.Push(i);
	}
	return a;
}

function Start()
{
	var array : Array = new Array();
	array.Push(0);
	array.Push(100);
	var integer : int = 65535;
	array.Push(integer);
	array.Push(0);
	print(array);
	string = Serialize(array);
	print(UnSerialize(string));
}

If I make integer 65536 i get an “OverflowException: Value is greater than Char.MaxValue or less than Char.MinValue”. Guess a char is 16-bits.

I tried printing some of the characters you get with the big numbers, and most of it is Chinese.

oh interesting, I didn’t know chars actually were 16 bits. I thought they were only 8 or so. Good to know, I haven’t actually tried serializing like this before, I’ll probably use it now for my scoreboard sending/receiving. :stuck_out_tongue:

But yeah, just RPC that string around and use the serializing and deserializing and you’re good.

I’m actually curious as to how your script even works, as I just tried it, and it’s giving me “cannot convert int to char” and “cannot convert char to int”

Thusly, on the lines that you have the conversion, I changed it to:

c = System.Convert.ToChar(intArray[×]);

i = System.Convert.ToInt32(arrayString[×]);

I don’t know what I am doing differently. This unityscript code compiles just fine for me and prints “{{”, but I think I might use that System.Convert because I think that would allow me to make the code take up less space, and I think it saves the program of having to allocate memory for c. Which doesn’t really matter on this scale, but I like thinking about what would happen if I were to scale it.

var integer : int = 123;
c = System.Convert.ToChar(integer);
var cc : char = integer;
print(c.ToString()+cc.ToString());