Search Unity

Looking for someone with experience with LLAPI

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

  1. Yoirgla

    Yoirgla

    Joined:
    Jan 2, 2015
    Posts:
    20
    Hey everyone.
    I'm looking for someone with LLAPI's NetworkTransport knowledge who can help with with a couple of issues concerning but not limited to :
    -(variable?) buffer size
    -amount of packets
    -QOS advanced informations
    -config + globalconfig
    my skype is Yoirgl (despicable me's minion icon)
    All help is welcome.
    Thanks

    Yoirgl.
     
  2. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    It would be good if you could provide some questions on what it is that you're having problems with, as your list at the moment is a little too generic to provide useful information. For the time-being, here's some feedback on your list:

    -(variable?) buffer size - please elaborate
    -amount of packets - if you are referring to how many packets/messages to send over time, it depends on your game. If you are looking to do a small arena game where you've got something like 2-10 players, you will get away with something like 20 messages per second. If you are looking to do an MMO or anything that requires a moderate to large scale, then you're talking more along the lines of 2-10 messages per second
    -QOS advanced informations - https://docs.unity3d.com/ScriptReference/Networking.QosType.html should explain what you need to know about each QOS type. If you need more info on a particular type or you're not sure what to use, please provide info on what you are planning to do and i'll recommend
    -config + globalconfig - please elaborate

    Let me know when you have further questions.
     
  3. Yoirgla

    Yoirgla

    Joined:
    Jan 2, 2015
    Posts:
    20
    Hello.

    Thanks for your reply.
    The idea is that I'm making an oculus rift mmo prototype and i am analysing the possibilities of UNet for this use case.
    My requirements are that servers need to be able to handle up to 5000 players, knowing that each player can see a total of 50 other moving elements (players/npc)
    I did some testing using NetworkTransport LLAPI, transmitting spell data, pop, player info and all occasional data (up to 1024 bytes/packet) using a Reliable Channel
    And I've been sending player position and npc positions each 10th of a sec using StateUpdate Channel.
    The problem I faced is that due to the max packet size of certain information i was forced to set my buffer size to 1024bytes even thou I'm mainly sending packets of position update who are somewhere between 10 to 50 bytes each.
    I do not now if it's due to the buffer size or not but out of 100 state updates sent by my server , my client maybe received 1-10 of those. causing npc's to depop and players to not be able to see each other.
    So if i already face this issue with as little as 50 packets to send I'm certain it's never going to be able to deal with lots of players. I tried sending the position information using UnreliableChannel following what I got spammed with some NoRessources errors.
    I'm currently trying with somehow a bit more success using NetworkServerSimple (still testing) but i don't understand how to get my packet size and packet loss to a minimum using the basic NetworkTransport class.
    I'm guessing Config and globalconfig settings can help me but the lack of information i find on it is making it extremely hard.
    The main question being really : can Unet LLAPI handle that much load at all ?
    The question concerning the QOS was about how to identify how many packets are lost and based on what criteria are they considered lost.

    Is this making my situation clearer to understand ?

    Yoirgl.
     
  4. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    I think we may have spoken about your project in the past. It's good to see that you're aiming lower with your send rate being 10 messages per second, although again I would recommend using this as an absolute maximum (try and aim for lower than this, and use client-side correction such as interpolation to account for visual discrepancies).

    I wonder if @Paul-Kirby can add some input here. He has done some testing on larger scales than I have, so hopefully he can give you some more tips than the ones i've already given in other posts for the numbers you are going for.

    To answer some of your other concerns though:

    You talk a little about channels, and I fear you may be using the wrong ones, so lets go over the basic concepts surrounding the QOS that unet provies:
    • by default, you are using UDP as your transfer protocol (unless you are building for WebGL, which I would highly recommend that you don't with the numbers that you are talking about, in which case you would be using TCP).
    • UDP, by design, is an unreliable transfer protocol. It is referred to as "unreliable", because it is designed to fire-and-forget. In short, you send a message and don't care about whether it gets there or not. It was specifically implemented for high-frequency transfer, such as what we end up doing in multiplayer games where we send updates about objects on a relatively high frequency.
    • it may seem like "unreliable" is a bad thing, but in actual fact it's excellent in scenarios where you are sending regular updates about something. So for example, if you are sending position updates about objects every 10th of a second, it's okay if one of those messages fails to reach the other end because another one will be sent shortly. This is known as "natural package loss" and it's one of the things that has made high-frequency transfer possible.
    • now, with QOS, any time you see "unreliable", you are simply using bog-standard UDP, where unet will send the message, and allow for natural package loss. In short, use an unreliable channel for anything that you are sending frequently and/or where you can account for package loss. And also, use this as much as you possibly can!
    • with any QOS related to "reliable", a layer exists in unet on top of the usual sending of messages. When you send a message on a reliable channel, unet adds a byte to the message to inform the other side that it is a reliable message, in which case the other side knows to "acknowledge" receipt of the message. It must then respond to the sender to notify them that the message was received. This should NEVER be used in high or even moderately frequent messages because if a message fails, unet will keep trying up to a certain number of times, causing blockage and pile-up before it finally disconnects the connection. So in short: use reliable for things like RPC, or infrequent messages where you need to garuntee delivery
    • state update channels are a little weird in my opinion. I've struggled to find a good use for them but ultimately if you end up in a situation where messages pile up, the last message will be the one that is sent and the first message will be the one that is received. All others are disregarded... it may just be that i've yet to build something that needs a state update channel but personally I can't think of a situation where you would want to use one.
    • although you don't talk about them (yet), I figured it worth mentioning:
      - the "fragmented" variants help when sending HUGE amounts of data in one single message. I would only use this if you're planning on sending something like a encoded media file, such as an image. Otherwise, you should avoid using fragmented channels and just make sure that your message sizes are within acceptable boundaries

      - the "sequenced" channels help to ensure that messages are sent and received in the correct order. This causes a little bit of overhead (due to the added byte(s) that are send to state the ordering of the messages, and also to ensure that messages are processed in the correct order) but helps to account for the natural disordering of messages. Since you will find that the time that it takes to send a message can vary from message to message, messages will naturally end up disordered from time to time. This should rarely cause you any problems though so in theory you should always be able to avoid sequenced channels, but in some cases they are useful

      - an allCostDelivery channel is just a high-priority reliable channel. If your networking involves system or internal processes, such as connection/disconnection or other important notifications, then use this channel. Otherwise, never use this channel.
    As mentioned above, this is because you're using a state update channel. Only the last message is being sent (from the server), and the first message is being received (on the client).

    We spoke breifly about this in another post, but this ultimately comes from a lack of internal resources (rather than system resources such as CPU). From my testing, it appears to indicate that you are running out of pools or buffers. Some ConnectionConfig properties have been said to help here, such as raising the maximum message count/size, but these appear to only relate to reliable messages so i'm not entirely sure why you would see this for unreliable messages. My gut feeling though is just too many messages going though the network...

    For you, the absolute key is getting your message count as low as possible. As mentioned before, this will largely be done by lowering your send rate (and accounting for that on the client), but will also be done using other techniques such as interest management, and making sure that you combine many small messages into one larger one. You will find that your networking is far more efficient if you combine many small messages into one larger one. You just have to be clever about how you set that up and handle it.

    We also spoke briefly about multi-threading. If you are getting to a point where you just cannot get what you want out of unet, it's very likely that your ultimate bottleneck is that unity is designed to be used to build primarily single-threaded applications, with limited support to multi-threading. I am fairly sure that unet already offloads some work to worker threads but even if it does, it wont be doing it as efficiently as if you were to do it yourself.

    Just don't. Although the NetworkServerSimple class is a stripped back version of the NetworkServer HLAPI class, it still expects you to use HLAPI functionality. At minimum, you will use registered handlers (check NetworkServerSimple.RegisterHandler) to handle messages, rather than the much leaner NetworkTransport.Receive. I've been forced to use NetworkServerSimple in my project because I need websocket support. Unless you need the same, stick to the LLAPI as you absolutely need all the performance you can get.

    For your other concerns, particularly related to the upper limits of unet, i'll leave that for @Paul-Kirby to discuss (if he is willing) as he has done some bench-marking on that.

    Hopefully this helps. Good luck!
     
    Cuttlas-U likes this.