Search Unity

How to implement a possibility to join existed sandbox game with async loading?

Discussion in 'Multiplayer' started by Artaani, Mar 20, 2018.

  1. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    423
    This is quite a complex question so I will try to explain it in details.

    There is many complex sandbox games where world generated procedurally and \ or by players. For example:

    Minecraft
    Space Engineers
    Empyrion Galactic Survival
    7 days to die
    etc

    In these games, when new players connecting to existed game - all players who already in the games is not paused, the game runs normally for them, they may continue to walk, craft, build, terraform etc.

    At the mean time, a player who connecting the game, downloading a save file. The save file may be big, so download process may take up to several minutes. But after downloading will be completed, the new player just will join the game and entire world will be perfectly synced.

    How it is possible?

    Because while a new player downloaded a save file of the world, many other players who already in the game built a lot of new staff and mined a ground using shovels and pickaxes.
    It means that world save file which will be downloaded by the connected players is outdated, because others players already managed to dig a hole which is not exist in the save file which was saved before that (when connected player just started to join a server).

    Okay, I am aware of buffered instantiation of prefabs. For example, if others players spawned some cubes, these cubes will be buffered and newly connected player also will have these cubes after joining process will be completed.

    But not entire world can be buffered. What about voxel terrain and digging? RPC can't be buffered at all (in UNET), but even if it will be possible, we can't buffer each time when someone dig a ground with the shovel, it is a lot of data.

    So how we can synchronize a hole in the ground which was digged while new player downloaded a save file of world?
    Of course we may just set the game on pause, but this is a bad solution for a players who already in the game and should wait for connection.

    I realize that it is very complex question to describe it in two words, but maybe someone may show me a direction where to work? Or maybe you saw a good article about this feature?

    Thanks.
     
  2. HarryMcCaffery

    HarryMcCaffery

    Joined:
    Oct 16, 2016
    Posts:
    14
    Minecraft divides the world into small chunks- and only load the ones close by. As the player moves the client loads new chunks from the server. I’m sure those other games work the same way.
     
  3. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    423
    Sounds reasonable.
    But what if other player will modify the chunk while it will be downloaded by connecting player? This is rare situation, but still possible.
     
  4. l3fty

    l3fty

    Joined:
    Mar 23, 2013
    Posts:
    87
    Actually not a very rare situation, for my game Woodfel I manage all these situations by queuing such events so they can be handled and distributed in an orderly fashion. There's a balance to be found in the chunk size so that you aren't doing too much work when sending chunks out, but also you can make optimisations like caching compressed chunks (until they are altered).
     
  5. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    423
    Oh! Seems like you know a solution. Could you please explain it in more details?

    So, as far as I understood, you are implemented your own system for queue of all RPC?

    For example:
    1. I am a client and I just connected to a server, now I am downloading a world data and waiting
    2. Someone on the server started to dig a ground and sent RPC about that
    3. I am received this RPC but I still don't have any ground, so instead of modifying of terrain, I added this information somewhere in the list (queue)
    4. I completed downloading and loaded a world
    5. Now I should perform all actions stored in my list (perform all RPC which I missed)

    And this should be done for every RPC (digging, crafting etc)? Every RPC should be added in custom list and performed later.
    Did I understood it right?
     
  6. HarryMcCaffery

    HarryMcCaffery

    Joined:
    Oct 16, 2016
    Posts:
    14
    That sounds like it would work. You could just create a queue for rpcs as you join, and then execute them all after the world loads.
     
    Artaani likes this.
  7. l3fty

    l3fty

    Joined:
    Mar 23, 2013
    Posts:
    87
    Aye that's the gist of it, and as long as you only operate on your data set via that queue it should all be quite safe.

    I used UNet messages rather than RPC's, and both the server and client put the recieved operations into queues to handle when ready. Also if you can guarantee message ordering to the clients they can assume any chunk edits they received prior to the chunk are contained within that chunk, or for added safety you can send a 'version' or operation number with the messages.

    Potentially you could thread the send chunk task/operation on the server too, if it looked like it could be a hold up. You would want to create a copy of the chunk in memory for the thread to use though, and that in itself might be just as slow with the memory allocation. That's not something I've tried yet though.
     
    Artaani likes this.
  8. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    423
    Thanks you both for information.

    Interesting. It is the second time when I saw that someone prefer NetworkMessages instead of RPC.
    Sounds like something much complex, but I will try to learn it.
    Thanks.