Search Unity

Disable state synchronization

Discussion in 'Multiplayer' started by recon, May 14, 2012.

  1. recon

    recon

    Joined:
    Nov 28, 2009
    Posts:
    119
    So Iv'e hit a roadblock when I recently decided to implement networking in my project.
    I wanted players be able to connect in the middle of a running game that has been going for a while, some notes here is that the world is completely dynamic and must be sent to the client before anything else can happen.

    Now immediately when a client successfully connects it starts receiving state synchronization calls from all the NetworkViews on the server, which in turns throws errors like "View ID AllocatedID: X not found during lookup. Strange behaviour may occur" and "Received state update for view id' AllocatedID: X' but the NetworkView doesn't exist".

    I have looked through the API and found no way to disable state synchronization calls other than
    Code (csharp):
    1. Network.isMessageQueueRunning = false;
    Problem is that this blocks all RPC calls as well and I need those to transfer the world state etc.

    I saw this thread with a similar problem and using a wonky workaround that destroyed all networkviews on all machines and recreated them seem to have worked out, but that seems like a poor solution to this problem.

    Another workaround solution I thought of was to pre-create the maximum amount of networkviews that is allowed in a session, assign them the full range of networkviewid's and keep them there until the client is done syncing the world state. This solution is terrible as well since a lot of redundant data will be transferred to the newly connected client before the world state has been passed so I would prefer a better solution.

    This brings me to my question regarding the thread title, why is there not a simple way in Unity to disable all state synchronization calls on a client while keeping RPC calls unaffected?
    Code (csharp):
    1.  
    2.  
    3.     // In a perfect world I would be able to do this:
    4.  
    5.     public void ConnectToServer()
    6.     {
    7.         // Disable all OnSerializeNetworkView calls before world has been fully synced.
    8.         Network.enableStateSynchronization = false;
    9.        
    10.         // Connect to server here..
    11.     }
    12.     public void WorldFullySynced()
    13.     {
    14.         // We have transferred the world state, enable state synchronization again!
    15.         Network.enableStateSynchronization = true;
    16.     }
    17.  
    This such a fundamental missing feature for any serious multiplayer game I would like a really good explanation on why this isn't currently possible in Unity (Im using the latest version 3.5.1f2), or if it is a planned feature in upcoming versions.
    Also if anyone has overcome this limitation in a better way than those I mentioned, then please share.
     
  2. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,687
  3. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    you can just use a global flag and when its not meant to sync, you just write the same data into the sync (ie not picking up new data). if you set the syncronization correctly to delta, then it will not send data anymore.
     
  4. recon

    recon

    Joined:
    Nov 28, 2009
    Posts:
    119
    On the client? As Im using a authoritative server I couldn't do it on the server as that would halt the game on those already connected and playing. I suppose it might work if I did the approach where I create the maximum available networkviews and set their stateSynchronization to Off then switch it back on once world syncing is done. This doesn't seem to be recommended in the docs however: "It is your repsonsibility to ensure that NetworkView's across all machines use the same reliability method. Do not change state reliability on the fly after state synchronization has already happened." http://unity3d.com/support/documentation/ScriptReference/NetworkView-stateSynchronization.html

    As I stated above, I cannot change the way data is written, the game would halt between all players already playing the game (Only the server is allowed to write, and must keep doing so at all times). And if I use a global flag to ignore received data on the newly connected client it would still flood the bandwidth while his world is brought up to sync.


    Hacky workarounds or not I still don't see a reason why this simple feature couldn't be implemented into Unity in the first place. Maybe it's not so easy to implement as I think it is, but then I would like to hear it from one of the Unity devs at least.
    I appreciate the suggestions, but there has to be a better way.
     
  5. George Foot

    George Foot

    Joined:
    Feb 22, 2012
    Posts:
    399
  6. recon

    recon

    Joined:
    Nov 28, 2009
    Posts:
    119
    Hmm, I must have completely overlooked that one.. A global flag might have been more convenient but it looks like this will do what I want. I will give it a shot :)
     
  7. recon

    recon

    Joined:
    Nov 28, 2009
    Posts:
    119
    I feel kind of silly now, can't believe I missed that method :p
    I got everything working, on the server in the OnPlayerConnected method I just loop through all networkview's, use SetScope(player, false) sync all world data, and when the client is ready I do the same thing except set SetScope(player, true) again. Works like a charm :)
    Still, a global flag would have been waay more convenient. If any Unity devs stumble onto this thread then consider that a feature request ;)

    Thanks for the help guys!