Search Unity

Question How do other games do it? Hitting the maxQueueSize in my dynamic world full of network objects.

Discussion in 'Multiplayer' started by Gazzzah, Jan 10, 2023.

  1. Gazzzah

    Gazzzah

    Joined:
    Jul 18, 2018
    Posts:
    16
    So before my question, some context. And I am still a noob at game dev and this is my first project at multiplayer stuff.

    I've build a world generation algorithm, it's full of trees, rocks, shrubs and fruit bushes.
    They get scattered across an island and partially re-spawn at the end of the day (but in different places)
    If the player destroys them then little resources pop out (also networkObjects).
    Fruit bushes can be picked, they have another networkVariable (dueDate) for when they will regrow their fruit.

    As soon as a client tries to join, it hits the max queue size.
    The error says: Couldn't add payload of size 270079 to reliable send queue. Closing connection 1 as reliability guarantees can't be maintained. Perhaps 'Max Send Queue Size' (98304) is too small for workload.

    I induced this error with 2000 items but the payload size varies based on however many there are.

    If I was using unity transport then I can just increase the max queue size (which feels like I'm setting myself up for future problems) but I've switched to facepunch steamworks, since having steam's "invite to lobby" is much more suitable for my games style and I cannot adjust the queue size in that (at least I don't think).

    Ok so I write a new Scatter object script and try to make it optimized AF.
    The only networkVariable is a struct that is made up of 5 shorts and 2 bools. I seem to be able to fit 1424 objects into the queue size. Which sounds great! But lets say that 4 players were spread out across the island each within visual range of 381 objects (trees, shrubs, bushes, rocks) then that would put me over. Perhaps I can make this work but that's not counting the players, the constructions, or items dropped on the ground. And then it would feel quite restrictive to have a max lobby size of 3.

    NOT a problem during runtime but as soon as another client tries to join, they get that same payload failure.

    I feel like I could solve this so easily if I just told the server, "hey, you don't need to spawn every single object on the clients instance at the same time, it can be a progress bar".
    Is there a way to do that?

    I'm thinking of games like Valheim where you have a dymanic world, covered in trees, rocks, monsters items and even terrain modification. How is everyone else doing this?

    Would really appreciate some insight if anyone can help.
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,892
    OMG no! Don‘t make every tree a network object! That is overkill, and completely unnecessary!

    Instead you need to have a deterministic world generation algorithm where the server tells a client „build the world (with these settings)“ and the algorithm‘s results will match the one on the server. Same for respawning trees. If a player chops a tree, that‘s an RPC message „remove tree“.
     
    tobiass and DevDunk like this.
  3. Gazzzah

    Gazzzah

    Joined:
    Jul 18, 2018
    Posts:
    16
    Wait.... you mean to say that you can use RPCs on non-networkObjects?

    How?
    I just wrote a little test

    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (Input.GetKeyDown(KeyCode.V)) TestServerRpc();
    4.     }
    5.    
    6.     [ServerRpc]
    7.     public void TestServerRpc()
    8.     {
    9.         Debug.Log("Server");
    10.         TestCLientRpc();
    11.     }
    12.     [ClientRpc]
    13.     public void TestCLientRpc()
    14.     {
    15.         Debug.Log("Client");
    16.     }
    When I press V on either device it outputs both logs and the other machine does not....

    Am I using the wrong kind of RPC or something?
     
  4. Gazzzah

    Gazzzah

    Joined:
    Jul 18, 2018
    Posts:
    16
    Omg. Huge smooth brain moment. I figured it out.

    You just have one networkObject to manage an array of trees, you can even just send messages with an index and a placement… I cannot believe it’s taken me this long to figure this out…
     
    CodeSmile and DevDunk like this.
  5. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,892
    Sometimes it's hard to see the manager for all the trees. :D
     
    simon-lemay-unity likes this.
  6. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    I would also recommend updating NGO to 1.1.0 or later (the latest is 1.2.0). That will remove the need to tweak the send queue size of Unity Transport when there's a lot of objects to synchronize.
     
    DevDunk likes this.
  7. Gazzzah

    Gazzzah

    Joined:
    Jul 18, 2018
    Posts:
    16
    Does this apply if I'm using a different transport? Like a Steamworks transport?

    I'm mainly using Unity Transport for internal testing (and learning) since it works with ParallelSync
     
  8. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    441
    The 'Max Send Queue Size' issue you mentioned in your original post is specific to Unity Transport, since the queue being overflowed is implemented by it. The exact same issue would not occur for other transports. With that said, there might be queue/buffer size limitations in other transports that would manifest in other ways. Unfortunately I'm not familiar enough with the community transports to offer any insights on this.
     
  9. Gazzzah

    Gazzzah

    Joined:
    Jul 18, 2018
    Posts:
    16
    All good. Yeah I've found similar things. There are limits on the other one I'm using as well but I don't believe it's configurable.