- Home /
Host Migration ?
Does Unity provide anything of this nature?
Are there any examples that show how other people are doing this?
Thanks, stringa
Answer by gecko938 · Jan 20, 2012 at 11:06 PM
Finally have a decent working solution for this!
This solution uses the version of Network.Connect that takes a GUID. It has taken a fair amount of effort to implement/test/refine (the last few weeks) and unfortunately entails a lot of application specific code, but at least it is possible.
I've revised my original answer below. This is strictly using Unity's networking system:
Each player communicates his GUID (Network.player.guid) via a buffered RPC to everyone in the session when he joins -- send it along with the details about the player's avatar (color, name, etc).
Every player locally now has a list of all the other player GUIDs in the session. This is the host candidate list, used to choose the next host when the current host disconnects.
The host candidate list must always be sorted in a way that guarantees an identical order on every machine. You can sort the list by the NetworkPlayer id, or it could even be sorted by GUID. You could also just have the current host dictate the order. Ideally, though, the sort would also take into account the NAT type, so players with greater NAT compatibility are at the top.
- Now, if a client loses connection unexpectedly, he does one of two things:
If he is next in line to be host, he immediately initializes and registers a new server.
- The other players wait a second or so, and then call Network.Connect( nextHostGUID ). This connects directly to the new host via the facilitator, bypassing the need to poll the master server for a list of games.
The client attempts to join the host a couple of times before giving up. He then repeats this using the next host candidate in the list. Eventually everyone will either connect to a new host, or end up hosting a new game locally.
(caveat: To connect to hosts that have no NAT and therefore possibly not registered with the facilitator, you MAY need to poll the master server for a host with the desired GUID.... It may also be possible to just always force migrated hosts to useNAT, so he registers with the facilitator. I don't have a machine without a NAT, so I've not been able to test this case yet.)
In the best/typical case, everyone will be reconnected after a few seconds of waiting. The new host can determine that everyone is reconnected by checking any new joiners against the host candidate list.
Once everyone is reconnected, it's time to migrate the networked game objects over to the new session. The original NetworkViews are no longer valid in the new session. So the old NetworkViews must be destroyed and then recreated with new viewIDs by the owning player, and the new view IDs must be transmitted to everyone so they can do the same. Networked objects belonging to the original host, or by any players that failed to reconnect will either need to be destroyed or assigned new owners (I personally have gone with the destroy approach).
I recommend pausing the game during this whole process, so unfortunately not completely seamless. You may or may not find that is necessary, but bear in mind syncing will be broken until everyone is reconnected. If you do pause, the host can send out a synchronized time of when to resume gameplay.
And there you have it... a migrated session. Your details may differ some based on your network architecture (my game has each player authoritative over their own state), but I think the basic approach will work regardless.
I would love to know how to do this. Your idea is the only solution I can think of. I know Raknet (the middle-ware that Unity uses) supports host migration...
That was awesome !!!!!!!!!!!!!!!! Thank you for this solution. I've just implemented this idea. It's working fine. But there are some more problems handling sudden disconnects like NetworkDisconnection.LostConnection.
What if unity includes some OnPre... events like On*Per*DisconnectedFromServer :)
Glad to hear the host migration solution is working for you!
What issues are you having that would require an "OnPreDisconnectedFromServer" function to solve?
I Just want to run my custom $$anonymous$$igrateHost method to another player before OnDisconnectedFromServer event.
@ND I know this is an old thread but just wanted to propose a solution for anyone dropping by: Unity can't tell when a host is going to disconnect. Perhaps the player suddenly lost their internet connection and disconnected. However, if you provide the player a way to quit (i.e. through the menu), you could do any pre-disconnect actions/RPCs you wanted and then disconnect the player.