can't understand sendRateOnSerialize

Hi there,

I just did some profiling on the OnPhotonSerializeView method to see if it was called the correct number of times, and the results seem weird to me:

let's say my settings are:
SendRate = 30
SendRateOnSerialize = 20

the photonView is set to Unreliable. So from what i understand, it will always send updates even if the values do not change, this should make the calls to OnPhotonSerializeView consistent.

So, every time OnPhotonSerializeView is called on the character, i get the time since the last time it was called and put that time in an array containing a 100 or so values (tried with 1000 too just to be sure). i displayed the medium of the values in said array, expecting to see something around 50ms (20 frames per second makes for 50ms between frames yes?) with my settings, i get around 65... with other settings it's the same i always get more time than i expect between calls to OnPhotonSerializeView(), on the receiver and on the sender side too...

Why is that? is there something i don't know or forgot to take into account?

Thank you for your answers =D

Comments

  • I'm sorry i meant the Mean, and not the Medium (which is a completely different word, english is weird :neutral: ) and i can't edit my post anymore.
  • DandS
    DandS
    edited November 2017
    Hi again,

    I found the source of the problem, in the PhotonHandler.cs script (which is part of the plugin, it is not my code), in the Update function, there is a timer used to call PhotonNetwork.networkingPeer.RunViewUpdate() on regular time intervals.

    here is the code:
    int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);  // avoiding Environment.TickCount, which could be negative on long-running platforms
    if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize)
    {
    PhotonNetwork.networkingPeer.RunViewUpdate();
    this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize;
    this.nextSendTickCount = 0; // immediately send when synchronization code was running
    }
    the problem is that Update is only called every 16 ms (in most cases at least)
    which means that if nextSendTickCountOnSerialize is for example 50, but the update is called when currentMsSinceStart = 48, OnPhotonSerializeView (called by RunViewUpdate() in the code) won't be called this update, it will be called on the next update at currentMsSinceStart = 64, then nextSendTickCountOnSerialize is set to 64+ updateIntervalOnSerialize
    let's say updateIntervalOnSerialize = 50 ( thats a sendrate of 20 times per second) then nextSendTickCountOnSerialize = 64+ 50 = 114...
    then we wait a frame, update is called as currentMsSinceStart = 80, then it's called at 96, then at 112, then at 128, that's bigger thannextSendTickCountOnSerialize (114), so we call OnPhotonSerializeView, but the time between the two calls is not 50 ms as it should be, it is 64 ms, and then it goes on like this, so instead of the 20 sends per second i set, i get roughly 15 sends per second in that case, but for every value there will be a difference from what is set in the sendRateOnSerialize

    the exact same thing happens with the normal SendRate value that is used in another piece of code just below by the way.

    i made a simple correction on my end:
            int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);  
    if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize)
    {
    PhotonNetwork.networkingPeer.RunViewUpdate();
    ///////////////////////////////////////////this next line
    this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize - (currentMsSinceStart - this.nextSendTickCountOnSerialize);
    ///////////////////////////////////////////
    this.nextSendTickCount = 0;

    currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);
    if (currentMsSinceStart > this.nextSendTickCount)
    {
    bool doSend = true;
    while (PhotonNetwork.isMessageQueueRunning && doSend)
    {
    // Send all outgoing commands
    Profiler.BeginSample("SendOutgoingCommands");
    doSend = PhotonNetwork.networkingPeer.SendOutgoingCommands();
    Profiler.EndSample();
    }
    ///////////////////////////////////////////////////and this line too for sendRate
    this.nextSendTickCount = currentMsSinceStart + this.updateInterval - (currentMsSinceStart - nextSendTickCount);
    ///////////////////////////////////////////////////
    }
    }
    that's it for me, bye =D
  • When we set this.nextSendTickCount = 0 in the upper block, you get a wrong result in the lower additional line.
    Otherwise, you're right. There is some "jagging" due to frame duration. You're making a good point to compensate for that. We'll have a look at it for PUN in general.
  • Uh... i completely missed that nextSendTickCount = 0, thank you for pointing that to me, i'll update my code right away.
    Also isn't that nextSendTickCount = 0 line making the SendRate a little faster than it is set to since it "speeds up" the sending of all commands? ( that is if sendrateOnSerialize is lower than sendrate )
    Is this on purpose? What for?
    Sorry I'm just curious =P
  • Ups. Missed this one.
    Yes, it's making the send rate faster but avoids local lag (which is usually more important than a fixed send rate).