Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Unity Multiplayer Proper way to destroy NetworkMatches

Discussion in 'Connected Games' started by Necromantic, Jun 15, 2015.

  1. Necromantic

    Necromantic

    Joined:
    Feb 11, 2013
    Posts:
    116
    What's the proper way to destroy a NetworkMatch?

    When I try to use DestroyMatch on the NetworkMatch with either creating a DestroyMatchRequest with the networkId set or just passing the networkId from the MatchInfo I get the following Response:
    I'm basically making a game that automatically matches up two people at "random".
    I first search the MatchList and if there is no suitable match it creates one and acts as the host or if one is found it joins as a client. So either after connecting the clients or after the game ends I want the Match to be removed. But I don't seem to be able to manually remove it. Meaning sometimes if I try to start a new game just after ending another one it will find the remainder of the old match and try to join it, basically connecting to nobody.
    Destroying the NetworkMatch component doesn't change anything either.
     
  2. JeremyUnity

    JeremyUnity

    Unity Technologies

    Joined:
    Mar 4, 2014
    Posts:
    147
    Matches are cleaned up automatically, as are clients that don't send a packet to relay for 30 seconds. That's the shortly after timing window you're seeing.

    That error looks like a poorly formatted way of the server saying the client you're connecting from is already disconnected; Once that happens it can no longer manage the network it was involved in.

    In other words, in order to destroy a network the client requesting the destruction needs to be the host for the match and connected. It looks like the disconnection had already happened in this case.
     
  3. Necromantic

    Necromantic

    Joined:
    Feb 11, 2013
    Posts:
    116
    What exactly is the host connection though? Because when you create a match you don't have to actually join it.
    I get the exact same error when I try to destroy the match just after both the client/server and the client connected to each other, so when they apparently are still connected because that connection has just been established through the MatchInfo.

    This is a simplified version of my connection logic. Am I missing something? All of it gets called, just with a failure for the DestroyMatch. Setting the access token does not change the behaviour. (Am I missing something?)
    Code (CSharp):
    1.  
    2.     public void OnServerConnect(NetworkMessage msg) {
    3.         networkMatch.DestroyMatch(matchInfo.networkId, OnMatchDestroy);
    4.     }
    5.  
    6.     public void OnMatchCreate(CreateMatchResponse createMatchResponse) {
    7.         if (createMatchResponse.success) {
    8.             //Utility.SetAccessTokenForNetwork(createMatchResponse.networkId, new NetworkAccessToken(createMatchResponse.accessTokenString));
    9.             matchInfo = new MatchInfo(createMatchResponse);
    10.             NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnect);
    11.        
    12.             ConnectionConfig config = new ConnectionConfig();
    13.             config.AddChannel(QosType.ReliableSequenced);
    14.             config.AddChannel(QosType.ReliableSequenced);
    15.             NetworkServer.Configure(config, 2);
    16.        
    17.             if (NetworkServer.Listen(matchInfo, 6789)) {
    18.                 client = ClientScene.ConnectLocalServer();
    19.  
    20.                 ClientScene.RegisterPrefab(playerPrefab);
    21.                 ClientScene.RegisterPrefab(ballPrefab);
    22.             } else {
    23.                 Debug.LogError("Error listening on port " + 6789);
    24.             }
    25.         } else {
    26.             Debug.LogError("Error creating match");
    27.         }
    28.     }
    29.  
    30.     public void OnMatchJoined(JoinMatchResponse joinMatchResponse) {
    31.         if (joinMatchResponse.success) {
    32.             //Utility.SetAccessTokenForNetwork(joinMatchResponse.networkId, new NetworkAccessToken(joinMatchResponse.accessTokenString));
    33.             matchInfo = new MatchInfo(joinMatchResponse);
    34.             client = new NetworkClient();
    35.  
    36.             ConnectionConfig config = new ConnectionConfig();
    37.             config.AddChannel(QosType.ReliableSequenced);
    38.             config.AddChannel(QosType.ReliableSequenced);
    39.             client.Configure(config, 1);
    40.  
    41.            ClientScene.RegisterPrefab(ballPrefab);
    42.            ClientScene.RegisterPrefab(playerPrefab);
    43.  
    44.            client.Connect(matchInfo);
    45.         } else {
    46.             Debug.LogError("Error joining match");
    47.         }
    48. }
     
    Last edited: Jun 15, 2015
  4. aspiering

    aspiering

    Joined:
    Aug 29, 2014
    Posts:
    12
    I would like some more information on this as well as I am running into the same issue. Is it making the assumption that server would also be connected to the server as a client ?
     
  5. aspiering

    aspiering

    Joined:
    Aug 29, 2014
    Posts:
    12
    Is there anything on this ? I am still having this issue and its actually preventing me from using this service because I don't want stale rooms showing up on the list.
     
  6. Necromantic

    Necromantic

    Joined:
    Feb 11, 2013
    Posts:
    116
    I've been busy the last few weeks but I see nothing much has changed. Can we get an update on this Jeremy?

    For me it's even worse since I have automatic matchmaking and it basically connects the clients to empty matches.
     
  7. Vennril

    Vennril

    Joined:
    Jul 12, 2014
    Posts:
    7
    Even if we pretend this would work, I'm seeing a problem:
    If the host disconnects unintentionally (because his connection drops), you would still end up with the same issue.

    So I think it would make more sense if the MatchList request wouldn't return empty matches to begin with. - Which I suggested in another thread, but no info on that yet.
     
  8. Necromantic

    Necromantic

    Joined:
    Feb 11, 2013
    Posts:
    116
    In theory there might be use cases for empty Matches, like creating one but for whatever reason not joining directly.
    You could also just filter matches with 0 people in them but it would still be nice if this was actually working.
     
  9. isidro02139

    isidro02139

    Joined:
    Jul 31, 2012
    Posts:
    72
    FYI there is a channel on irc.freenode.net (#unity3d-unet) where people might have more answers eventually, seeing as unet is still in it's infancy ;)

    And some other resources here: https://goo.gl/UmBBpM
     
  10. Vennril

    Vennril

    Joined:
    Jul 12, 2014
    Posts:
    7
    I'm not so sure about that. You couldn't join that empty match afterwards, since you can't join matches with no host in it.

    How would you do that? I'm genuinely curious. ListMatch requests have no filter for that, and even the matches themselves don't seem to expose the number of players inside them.
     
  11. Necromantic

    Necromantic

    Joined:
    Feb 11, 2013
    Posts:
    116
    You get back a list of matches though and the info tells you how many people are connected to it.

    The problem is that in my case it still says there is one connection on it even though there isn't.
     
  12. Kristonitas

    Kristonitas

    Joined:
    Jan 16, 2013
    Posts:
    9
    I have been trying to do the same thing. The only quick solution I presume would be to have an offline list of matches, that you failed to join and the filter them out by yourself.

    This is the code I use for my simple 1v1 matchmaker:

    Code (CSharp):
    1.  
    2. void OnMyMatchList(ListMatchResponse matchList){
    3.         for (int i = 0; i < matchList.matches.Count; i++) {
    4. // Also check if failed to connect
    5.             if(matchList.matches[i].currentSize > 1)
    6.                 continue;
    7.             matchMaker.JoinMatch(matchList.matches[i].networkId, "", OnMatchJoined);
    8.             return;
    9.         }
    10.         //            startMyOwn
    11.         matchMaker.CreateMatch("name", 2, true, "", OnMatchCreate);
    12.  
    13.     }
    When I join an empty server (the second time at least), I get an error like this:
    But when I join the empty server the first time, it fails silently

    I hope there is a way to determine if everything went well on the callback "OnMatchJoined" (since it always fires), because the only other way is to check manually after a few seconds if you actually joined, but that would be also very slow and unreliable.

    The reason empty servers are created is that I can turn off my android game without quitting properly, f.e. Build&Run. If I quit, I can destroy match and it gets removed almost always.
     
  13. tribio

    tribio

    Joined:
    Oct 5, 2013
    Posts:
    25
    I don't get it.. but Unity 5 is still in beta?!!!!:confused:
    It's a few days that I using the new Networking and I found more problems than solutions here!
     
  14. Gorgor

    Gorgor

    Joined:
    Apr 28, 2012
    Posts:
    51
    Hi, anybody found a solution to this? Still happening to me :( Basically matchmaking is useless for final product thanks to this :(
     
  15. Terko

    Terko

    Joined:
    Apr 20, 2013
    Posts:
    28
    Having this issue too. Any known solutions?
     
  16. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    Ping

    I have the same problem... if the host disconnects, and tries to connect a few seconds after, he joins an empty lobby.
    Checking the number of players in the room does not help as it states there is one player, even if there is 0...
     
  17. Anisoropos

    Anisoropos

    Joined:
    Jul 30, 2012
    Posts:
    94
    Same here, hope they fix it soon :/
     
  18. UnityForge

    UnityForge

    Joined:
    Nov 13, 2012
    Posts:
    18
    same here
     
  19. carmine

    carmine

    Joined:
    Jan 4, 2012
    Posts:
    391
    This is definitely not happening.
    - I have a match that won't go away. I've tried rebooting, quitting Unity, etc. It's not going away.
    - I can attempt to Join it (it seems to think 4 players are connected) even though I'm the only one trying it (it's in development)
    - If I try to create a match I get an error that looks like my CCU is exceeded? However according to the list I only have 1 match that is 4 of 20 players?

    Please advise...

    Create Failed:[[UnityEngine.Networking.Match.CreateMatchResponse]-success:False-extendedInfo:Failed; CCU exceeded for appId=725151]-address:,port:0,networkId:0x0000000000000000,nodeId:0x0000,usingRelay:False
    UnityEngine.Networking.NetworkManager:OnMatchCreate(CreateMatchResponse)
    NetworkController:OnMatchCreate(CreateMatchResponse) (at Assets/_Assets/Scripts/Networking/NetworkController.cs:194)
    UnityEngine.Networking.Match.<ProcessMatchResponse>c__Iterator0`1:MoveNext()
     
    GrymmyD likes this.
  20. GrymmyD

    GrymmyD

    Joined:
    Dec 2, 2015
    Posts:
    42
    I am also experiencing this. In the past matches that were hosted and improperly exited (i.e. stop the debugger without leaving match cleanly) would be cleaned up in approximately 30 seconds. Today I've run into a scenario where a game that I created is lingering and isn't being GC'd due to inactivity. Also attempted quitting Unity / disconnecting network for minutes / rebooting same as @carmine.
     
  21. AndyUr

    AndyUr

    Joined:
    Aug 17, 2015
    Posts:
    16
    I'm struggling with a similar behavior, although I haven't encountered the limit with CCU yet.

    There is a lingering match that allegedly has 9 users in it. For my matchmaking I require only 1 match to exist with some specific name, so users can automatically join that one. Having duplicates of this match poses a problem with this.

    I tried calling Destroy on that match from my client. But I'm not sure if this is supposed to work, since I'm not the host of this lingering match. This is one of the messages I get.

    I'm right now trying to do what the message suggests, and do that check.
     
    GrymmyD likes this.
  22. GrymmyD

    GrymmyD

    Joined:
    Dec 2, 2015
    Posts:
    42
    Yup, that lingering match issue is exactly what I'm experiencing.
     
  23. pixel_maniacs

    pixel_maniacs

    Joined:
    Jun 25, 2015
    Posts:
    35
    Same here, how am i supposed to destroy a match? Another workaround would be to rename the match with a Tag once the host leaves. But I do not see any possibility to do so.
     
  24. Silktoid

    Silktoid

    Joined:
    Feb 4, 2016
    Posts:
    1
    Any updates on this? Does anyone know how to disconnect properly when the game is closed while still connected? I have tried disconnecting OnApplicationQuit, and it seems to work for the Windows standalone, but stopping execution in the editor still makes a match stay around until cleanup. The same proplem happens with the android build since OnApplicationQuit is never executed. Using OnApplicationPause in that instance isn't really a solution since then the client will disconnect from the server everytime it tabs out of the game.

    Using lochmanns workaround would help greatly since then it would be possible to filter out servers waiting for cleanup.
     
  25. RonnyKibet

    RonnyKibet

    Joined:
    Jul 7, 2015
    Posts:
    3
    Experiencing the same when re-entering the lobby to join another match. Previous connection cannot be destroyed.
    If anyone found a solution, it would be amazing to share.
     
    Chom1czek likes this.
  26. Julian-G

    Julian-G

    Joined:
    Sep 13, 2012
    Posts:
    2
    No updates since July!?
     
  27. asveron

    asveron

    Joined:
    Nov 2, 2016
    Posts:
    1
    I'm also experiencing the same issue.
    Not really sure the best way to destroy the match.
    When I do matchmaking I still run into the "empty rooms" where a player left but the room hasn't closed yet.

    I've tried this:
    networkManager.matchMaker.DestroyMatch (matchInfo.networkId, 0, networkManager.OnDestroyMatch);

    However when I search again, it still shows the room and it hasn't been destroyed.

    *Edit 3

    Found a slightly better solution.

    1. set your class to inherit Network manager.
    Code (CSharp):
    1. public class Matchmaker : NetworkManager {
    2. Override the OnClientDisconect function. Call your matchmaking function in it.
    Code (CSharp):
    1.     public void startMatchmaking() {
    2.         StartMatchMaker ();
    3.         SetMatchHost("us1-mm.unet.unity3d.com", this.matchPort, true);
    4.         matchMaker.ListMatches (0, 20, "", false, 0, 0, this.OnMatchList);
    5.         isMatchmaking = true;
    6.         isSearching = true;
    7.         cyclingSearchingText.isCycling = true;
    8.     }
    9.  
    10.     public override void OnClientDisconnect (NetworkConnection conn)
    11.     {
    12.         base.OnClientDisconnect (conn);
    13.  
    14.         print ("client disconnect");
    15.         // makes sure the disconnect happened before the game began
    16.         // you don't want to start another matchmaker during your game
    17.         if (!battle.isBattling) {
    18.             startMatchmaking ();
    19.         }
    20.     }
    After the server times out in 30 seconds, you'll be disconnected from the server and OnClientDisconnect will be called. Usually its less than 30 seconds because it starts counting down as soon as the host left, rather than 30 seconds from when you joined.

    I've tried using "public override void OnMatchJoined" but it has inconsistent results. Most of the time it'll say that I succeeded. But sometimes it realizes that the matchmaking failed because the host is not there. So perhaps you could call your startMatchmaking there as well if you want matchmaking times to be slightly more snug when it does notice it failed.

    I also noticed that after OnMatchJoined is called, the player network object is almost always created within 5 seconds. Perhaps you can set a timer to check if your player has been created after OnMatchJoined is called.
     
    Last edited: Nov 9, 2016
    kortenoever likes this.
  28. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    279
    K so I had the same problem and managed to fix it (I think).
    I don't know why it's so hidden cause preventing players from rejoining isn't that rare a feature..
    You need this for most 1v1 games (chess, card games, ..)

    Anyway, this is what you need. You need to unlist the match with the IsListed bool.

    When a player joins the game, the networkmanager calls OnServerAddPlayer.
    So you do what you need to do and then call the SetMatchAttributes
    Code (CSharp):
    1. public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    2.     {
    3.         GameObject player = Instantiate(playerPrefab);
    4.         player.name = "HumanPlayer";
    5.        
    6.         NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    7.         if (NetworkServer.connections.Count == 2) {
    8.                matchMaker.SetMatchAttributes(matchInfo.networkId, false, matchInfo.domain, OnSetMatchAttributes);
    9.         }
    10.     }
    Likewise when a host wants to disconnect, even when the host is waiting for players, run the same code and use the callback OnSetMatchAttributes to call StopHost(); after unlisting it

    Code (CSharp):
    1. public override void OnSetMatchAttributes(bool success, string extendedInfo) {
    2.         base.OnSetMatchAttributes(success, extendedInfo);
    3.  
    4.         if (success) {
    5.             Debug.Log("match no longer listed");
    6.             StopHost();
    7.         }
    8.     }
     
  29. JesusChrist17

    JesusChrist17

    Joined:
    Sep 17, 2016
    Posts:
    12
    does anybody know why if i wrote in my code networkManager.stopHost() , the unity server says that it has 1 people connected? ( match.currentSize returned 1 in find server with list match ). Thanks
     
  30. shivansh11

    shivansh11

    Joined:
    Jul 28, 2014
    Posts:
    5
    An amazing hack! It works! I was looking for a way to get past this problem for such a long time. Now I won't have to wait for 30 seconds! Thank you very much! :)
     
unityunity