Search Unity

Recommended ConnectionConfig Settings

Discussion in 'Multiplayer' started by Doghelmer, Mar 12, 2017.

  1. Doghelmer

    Doghelmer

    Joined:
    Aug 30, 2014
    Posts:
    120
    I just released a game on Friday making use of Unity's networking capabilities. While things have gone smoothly for the most part, a portion of my players have been having major connectivity issues. From the logs that they've sent me, typically the host will start outputting messages like these:

    Code (csharp):
    1.  
    2. (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
    3. Send Error: NoResources channel:1 bytesToSend:63
    4. (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
    5. Failed to send internal buffer channel:1 bytesToSend:29
    6.  
    At this point, the client stops receiving data. Pretty common stuff, but I wasn't anticipating it to be widespread.

    Many people don't seem to be having these issues at all. However, I'm thinking that a "band-aid" fix could be created by modifying the ConnectionConfig settings. While I recognize that these are initially set to their "ideals", obviously that's not cutting it for my game, which tends to be very fast action with a lot of stuff going on at any given time.

    I was wondering if anyone might be able make a recommendation on what values I might want to modify, and to what degree, to perhaps alleviate people's issues without hampering the experience too much. It might just be something I have to toy around with, I just don't really have an understanding of the implications of modifying these.
     
    Last edited: Mar 13, 2017
  2. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    So the recommended settings (coming from personal experience in playing around with them for performance tuning): as-is. Don't quote me on this, but after a fair bit of testing my game on various devices and some additional trial-and-error, when the config settings are left to their default settings I get the least amount of problems and the best performance.

    I have run into similar issues to yourself, particularly the dreaded NoResource error, which doesn't actually mean that you have run out of system resources (as you would think it does). It actually refers to internal resources such as the pools and buffers that unet sets up to handle incoming/outgoing messages.

    What I recommend is: first try and optimize your network code. If that doesn't work, temporarily consider modifying your connection config settings related to the maximum number of messages/counts (particularly the MaxCombinedReliableMessageCount and MaxCombinedReliableMessageSize). In your case, 63 and 23 bytes of overhead would suggest that the count needs to go up, rather than the size (you're sending too many messages, rather than too many bytes). Again though, if you do this, consider it to be temporary and start working on improving your network code.

    Some tips on improving your code:
    • I'll make an educated guess here and say that you're using a send rate somewhere within the 20-30 times per second range? This is a common mistake with newcomers to networking, as we think that we need to send as many updates per second as is needed to make things look "smooth". As a result, this is always the first mistake that we make. Judging by the game that you've made (which looks cool btw!), you should be able to have a very low send rate, potentially somewhere around the 2-5 frames per second. The key here is smoke-and-mirrors: the client-side of your game should be able to use techniques such as interpolation (take a look at Vector2.Lerp to smoothly interpolate the position of an object) to account for larger gaps between network updates.
    • combine many small messages into one larger one. Depending on how much you are relying on the HLAPI, this might prove difficult as it's much easier to do using the LLAPI (since you have more control). The ultimate goal is that say for example you have 10 objects all moving at the same time, you don't need to send 10 separate messages to notify all clients of the movement. You could send one message containing the updates for those 10 objects, which is far more efficient. Every message that you send comes with an overhead. For UDP, you have an overhead of 8 bytes plus however many bytes unity adds to the message internally (which can be a lot if you rely on the HLAPI). Not to mention, every message requres cpu time to serialize to/from byte arrays, and to handle the message. So, many small messages versus one larger combined message will both reduce your bandwidth usage and improve cpu performance.

      Note that unet does combine some messages for you, but from the testing that I have done it doesn't do a great job here. So I wouldn't recommend relying on unet to combine small messages into one larger one.
    Hopefully this helps, and good luck with your game. If you need further help, feel free to PM me.
     
  3. MechEthan

    MechEthan

    Joined:
    Mar 23, 2016
    Posts:
    166
  4. Doghelmer

    Doghelmer

    Joined:
    Aug 30, 2014
    Posts:
    120
    Thank you for the tips.

    Before you posted this, I ended up messing around and increasing MaxCombinedReliableMessageSize to 256 (double the normal), and this seemed to fix everyone's issues. Not sure what repercussions this might be having, but people's experiences seem to be roughly the same, minus all the desyncing.

    My send rate is actually 10 times per second for most commands, including character movement. Character movement is being handled by Network Transform, and that's really the only thing that's sending lots and lots of messages. There's probably more I could do to combine other messages together, but I feel like those are a drop in the bucket compared to movement, and the profiler confirms this. Not sure how much I can do here that I haven't tried already.

    Oddly, the desyncing issues were happening for only a portion of my player base. I was never able to reproduce them myself -- it appeared to be dependent on some aspect of the person's connection.
     
  5. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    This is absolutely great news! Thank you for bringing this to our attention.

    Based on the new documentation, it ultimately allows more automated combining of small messages resulting in less messages being sent in total (and actually less bytes overall). The repercussion will be more ram and cpu, since unet will need to allocate more memory to hold bigger arrays of messages, and processing bigger arrays means more cpu, although there will also be reduced cpu on the receiving end due to there being less messages to process. I'm not sure whether this effects each connection individually, or whether it simply effects the network overall, but either way it will use more system resources to improve bandwidth, so I guess it depends on which resources are more of a bottleneck for your target platform(s).

    EDIT

    From the new documentation on ConnectionConfig: "This class defines parameters of connection between two peers, this definition includes various timeouts and sizes as well as channel configuration."

    So, the increase in ram + cpu due to increasing your maximum combined message count/size will be multiplied by the number of connections. So if your server is to handle moderate to high numbers of players then you should aim to keep this as low as possible. Otherwise you should be okay to increase it.

    EDIT 2

    Also another interesting point. The ConnectionConfig.MaxSentMessageQueueSize also appears to relate to the NoResource error: "This buffer serves to smooth spikes in traffic and decreases network jitter. If the queue is full, a NoResources error will result from any calls to Send()"
     
    Last edited: Mar 14, 2017