Search Unity

MatchDesc MatchAttributes are always null

Discussion in 'Multiplayer' started by alexi123454, Jul 15, 2015.

  1. alexi123454

    alexi123454

    Joined:
    Jul 9, 2015
    Posts:
    8
    Hey guys,

    I'm making a basic little lobby-based multiplayer game where players can create and filter rooms based on some criteria (like level cap, whether it's playing or not, what map it's using, etc). When I create the match, I use a CreateMatchRequest to set all the basic options of the game (name, room size, password, etc), and then I use MatchAttributes to define the rest of the variables. Tossing the CreateMatchRequest into the CreateMatch function has everything working correctly as far as I can tell (the callback is successful, and the match is shows when I call ListMatches).

    However, when populating a room list using the matches variable of the ListMatches callback (ListMatchResponse.matches), while the basic information about each match is correct (the name and such), the matchAttributes of each one is null.

    Did I forget to set something up, or is this a known issue with UNET? Here's the code for match creation and listing:

    Code (CSharp):
    1. ///....
    2. CreateMatchRequest options = new CreateMatchRequest();
    3.             options.name = aName;
    4.             options.size = aOptions.size;
    5.             options.advertise = true;
    6.             options.password = "";
    7.             options.matchAttributes = new Dictionary<string, long>();
    8.             options.matchAttributes.Add("minLevel", m_roomLevelRangeMin);
    9.             options.matchAttributes.Add("maxLevel", m_roomLevelRangeMax);
    10.             options.matchAttributes.Add("StartGameTime", 600);
    11.             options.matchAttributes.Add("IsPlaying", 0);
    12.             options.matchAttributes.Add("MapLayout", m_presetListSelection);
    13.             options.matchAttributes.Add("MapSize", m_sizeListSelection);
    14.  
    15. NetworkManager.singleton.matchMaker.CreateMatch(options, OnMatchCreate);
    16. ///...
    17.  
    18.  
    19. ///List matches (this is in another function)
    20. NetworkManager.singleton.matchMaker.ListMatches(0, 100, "", OnListRoomsCallback);
    21.  
    22. public void OnListRoomsCallback(ListMatchResponse aResponse)
    23. {
    24. m_roomList = new List<MatchDesc>();
    25.             m_roomList.Clear();
    26.             foreach (MatchDesc match in aResponse.matches)
    27.             {
    28.                 m_roomList.Add(match);
    29.             }
    30.  
    31. if (m_roomList != null)
    32.             {
    33.            for (int i = 0; i < m_roomList.Count; i++)
    34.                       {
    35.                       ///this always displays true
    36.                     Debug.Log(m_roomList[i].matchAttributes == null);
    37.                       }
    38.             }
    39. }
    40.  
    41.  
     
    boxels likes this.
  2. JeremyUnity

    JeremyUnity

    Joined:
    Mar 4, 2014
    Posts:
    147
    It's a known issue right now. The match attributes are for future compatibility with the Matchmaker, where you'll be able to add custom attributes and filter against them exactly like you're doing now.

    There are some issues transferring the complex attribute data to Matchmaker in the 5.1 code so that feature isn't available yet however. We're working on fixing that but i don't have a specific version it will be fixed in.
     
    boxels likes this.
  3. alexi123454

    alexi123454

    Joined:
    Jul 9, 2015
    Posts:
    8
    Ah, thanks for the information Jeremy. Could you suggest another way for me to store information about a match that any player could access before joining that match (or at least during the match)?
     
    boxels likes this.
  4. JeremyUnity

    JeremyUnity

    Joined:
    Mar 4, 2014
    Posts:
    147
    Your best bet is a bit of a hack and i'll apologize up front for it.

    As you noted basically everything else in the request messages work. You can make up for some of the missing functionality by using the name and eloScore variables.

    eloScore is a numerical value that we aggregate based on your input to help generate the listmatch results. The logic is a bit hidden but here's what we do:

    In CreateMatch or JoinMatch each client can indicate their own eloScore, a numeric value based on whatever metrics you feel are important to derive a true skill style indicator for that player.

    In ListMatch, when we look at all the possible matches we compute the average elo score for each match, based on the average of all players currently in that. Then when we sort the pages we return we order according to the difference between a group's average and the elo of the player looking for a match as indicated in the ListMatch request and the computed average of each group. You'll see the closest matches on the first page and greater deviations as you go through the pages after that.

    For some background on Elo, check out https://en.wikipedia.org/wiki/Elo_rating_system

    In the end the idea is to allow for a flexible sorting we can do on the server side backed on any metrics you decide are important.

    The other tool is the name field itself, and this is where we get into dirty hack territory. The name is a string who's max is 256 characters, which is admittedly on the short side but you can pack more data into it than just the name for now if you desire. For instance you could pack info in this manner "Name=Joe:MinLevel=3" etc. The one caveat i'd add for best results avoid the following characters since we do special escaping for them before our backend processes them

    [ ] % _

    Then in ListMatch when you specify a name you can specify an attribute, like "MinLevel=3" and you'll only get match results that contain that info. Additionally you can look through the matches returned after this high level filter and do additional local filtering to find exactly the match you want, so it's probably best to filter the name request against whatever will eliminate the greatest number of uninteresting matches and then do the local filtering based on those results.

    It's not perfect for sure, and you're limited to filtering on name against one attribute since the wildcard search is basically *name* where name is the string specified in the ListMatchRequest, but hopefully it's something for the short term.

    Longer term the MatchAttributes will allow complex searches against values using the ListMatchRequest where you can specify less than, equal to, and greater than filters which will obviously be a lot more useful than this approach.
     
    boxels likes this.
  5. tribio

    tribio

    Joined:
    Oct 5, 2013
    Posts:
    29
    Create a match:

    Code (CSharp):
    1. CreateMatchRequest create = new CreateMatchRequest();
    2. create.name = "Tribio Room";
    3. create.size = 4;
    4. create.advertise = true;
    5. create.password = "";
    6. create.eloScore = 3;
    7. matchMaker.CreateMatch(create, OnMatchCreate);
    then in the list matches:

    Code (CSharp):
    1. public void OnMatchList(ListMatchResponse matchListResponse)
    2. {
    3. if (matchListResponse.success)
    4.         {
    5.             if(matchListResponse.matches.Count > 0)
    6.             {
    7.                 for(int i = 0; i < matchListResponse.matches.Count; i++)
    8.                 {
    9.                     Debug.Log(matchListResponse.matches[i].averageEloScore);
    10. ...
    11. }
    Resutl 0! Always 0... :-(
     
    boxels likes this.
  6. JeremyUnity

    JeremyUnity

    Joined:
    Mar 4, 2014
    Posts:
    147
    Thanks for the report, I've created a public bug for this. 712749.
     
    boxels and tribio like this.
  7. mbouffard

    mbouffard

    Joined:
    Jun 28, 2013
    Posts:
    19
    Hi,

    When do you think we'll be able to use Attributes or AverageEloScore?

    I also have the same issue: averageEloScore is always 0. The public bug #712749 is now marked as closed, with voting disabled because it's fixed.
     
  8. Lofar42

    Lofar42

    Joined:
    Oct 11, 2014
    Posts:
    12
    @JeremyUnity I understand you are in Beta, but a cheeky question anyway: Is there an ETA on the matchAttributes getting returned with the MatchDesc object? Thanks
     
    Last edited: Jan 23, 2016
    TheWarper likes this.
  9. carmine

    carmine

    Joined:
    Jan 4, 2012
    Posts:
    394
    Any chance of having a match attribute that is a string value? Having 1 string that could be set as a json string then serialized/deserialized would be much more useful then just long values.

    Also, can it be updated during the match?
     
  10. Gorgor

    Gorgor

    Joined:
    Apr 28, 2012
    Posts:
    51
    Yes, matchAttributes is always null and ELO is 0. Great matchmaking service!! :D Ok, time for me to start parse the "Name" of the match.......PLEASE FIX ASAP! Thanks.
     
    Deleted User and Craneballs like this.
  11. RavenTravelStudios

    RavenTravelStudios

    Joined:
    Oct 15, 2015
    Posts:
    100
    Same here. We can workaround on this for now, but we hope you can fix the bug asap guys ... Thank you so much :)
     
    TheDelhiDuck likes this.
  12. Fenrus89

    Fenrus89

    Joined:
    Mar 11, 2013
    Posts:
    1
    Hi guys! I see issue about ELO but don't see registered issue about matchAttributes... Can you say issue number or register issue about matchAttributes always null in match description?
     
  13. rahulkj

    rahulkj

    Joined:
    Feb 10, 2015
    Posts:
    11
    It blows my mind. The consistency at which Unity releases broken features
     
  14. SniperED007

    SniperED007

    Joined:
    Sep 29, 2013
    Posts:
    345
    I can't believe that it's almost a year later and we still don't have Match Attributes support !?
     
  15. glitchers

    glitchers

    Joined:
    Apr 29, 2014
    Posts:
    64
    Is there any update for this? All I can see in the Roadmap is Host Migration, Server Library and Standalone Server Simulator.

    If this feature isn't functional please amend the documentation as it is misleading that the feature isn't actually implemented.

    I'm sure everyone here has made a script to pack the attributes into the name of the match but here's mine so you don't have to write the same code to patch this. Just call PackMatchRequest before you create the match and UnpackMatchDesc when you get your list back.

    Code (CSharp):
    1.  
    2.     using System.Text;
    3.     using System.Collections.Generic;
    4.  
    5.     using UnityEngine;
    6.     using UnityEngine.Networking;
    7.     using UnityEngine.Networking.Match;
    8.     using System.Collections;
    9.  
    10.     public static class NetworkUtil
    11.     {
    12.         #region Match Request
    13.         private static string kPackKeyDelimiter = "||";
    14.         private static string kPackAttrDelimiter = "&&";
    15.  
    16.         public static void PackMatchRequest( CreateMatchRequest matchRequest )
    17.         {
    18.             StringBuilder packedAttributeBuilder = new StringBuilder();
    19.  
    20.             if( matchRequest.matchAttributes != null && matchRequest.matchAttributes.Count > 0 )
    21.             {
    22.                 packedAttributeBuilder.Append( kPackAttrDelimiter );
    23.             }
    24.  
    25.             foreach( KeyValuePair<string, long> attr in matchRequest.matchAttributes )
    26.             {
    27.                 packedAttributeBuilder.Append( attr.Key );
    28.                 packedAttributeBuilder.Append( kPackKeyDelimiter );
    29.                 packedAttributeBuilder.Append( attr.Value );
    30.                 packedAttributeBuilder.Append( kPackAttrDelimiter );
    31.             }
    32.  
    33.             matchRequest.name = matchRequest.name + packedAttributeBuilder.ToString();
    34.         }
    35.  
    36.         public static void UnpackMatchDesc( MatchDesc matchDesc )
    37.         {
    38.             if( matchDesc.matchAttributes != null && matchDesc.matchAttributes.Count > 0 )
    39.             {
    40.                 Debug.Log("Match Attributes have been implemented!, Stop using this!");
    41.             }
    42.  
    43.             // if we have packed attributes, unpack them
    44.             if( matchDesc.name.IndexOf(kPackAttrDelimiter) != -1 )
    45.             {
    46.                 string[] packedAttributes = matchDesc.name.Split(new string[]{kPackAttrDelimiter},System.StringSplitOptions.RemoveEmptyEntries );
    47.  
    48.                 // name is always first
    49.                 matchDesc.name = packedAttributes[0];
    50.  
    51.                 matchDesc.matchAttributes = new Dictionary<string, long>();
    52.  
    53.                 for( int i = 1; i < packedAttributes.Length; i++ )
    54.                 {
    55.                     string[] attrComponents = packedAttributes[i].Split( new string[]{ kPackKeyDelimiter }, System.StringSplitOptions.None );
    56.                      matchDesc.matchAttributes.Add( attrComponents[0], System.Convert.ToInt64( attrComponents[1] ) );
    57.                 }
    58.             }
    59.         }
    60.         #endregion
    61.     }
    62.  
     
  16. Gamba

    Gamba

    Joined:
    Feb 8, 2015
    Posts:
    29
    Over a year later and I still don't see this on the roadmap. @JeremyUnity, do you know if this is still being worked on?
     
  17. hakankaraduman

    hakankaraduman

    Joined:
    Aug 27, 2012
    Posts:
    354
    Is there any update regards to how to add attributes to a match when creating one?