playgameservices / play-games-plugin-for-unity

Google Play Games plugin for Unity
Other
3.47k stars 966 forks source link

ILeaderboard.range filter not respected in ILeaderboard.LoadScores interface implementation #1746

Open Firemaw opened 7 years ago

Firemaw commented 7 years ago

Android 6.0.1 with GPGS 0.9.36 and Unity 5.5.3f1.

When performing a ILeaderboard.LoadScores() operation with a range filter, the incorrect ranks are returned. It seems this part of the standard Unity Social API has not been implemented properly.

I understand on the main page there is an example of how to use PlayGamesPlatform.Instance.LoadScores() which works for the most part (except for a high score caching issue). However, for all other code I am using the standard Unity Social API, which is cross-compatible with iOS (where I am not using GPGS), so it would be nice to use the same code for both instead of having to write two separate blocks to get nearby players on leaderboards. The other issue I have run into using PlayGamesPlatform.Instance.LoadScores() is #1534.

Here is the core code in question:

ILeaderboard clb = Social.CreateLeaderboard (); clb.id = leaderboardID; clb.range = new Range (urank, 5); clb.LoadScores ((bool csuccess) =>{ ... });

Here is the full code for the fetch that works on iOS, but not Android (incorrect ranks returned):

static void LoadCompetitors (string leaderboardID, int numEitherSide, GameObject uiObj, Action<string> callback)
{
        StringBuilder output = new StringBuilder ();
        ILeaderboard ulb = Social.CreateLeaderboard ();
        ulb.id = leaderboardID;
        ulb.SetUserFilter (new string[] { Social.localUser.id });
        ulb.LoadScores ((bool usuccess) =>
        {
            if (usuccess)
            {
                if (ulb.scores.Length > 0)
                {
                    IScore uscore = ulb.scores[0];
                    int urank = uscore.rank - numEitherSide < 1 ? 1 : uscore.rank - numEitherSide;
                    Debug.LogFormat ("{0}. {1} {2} ({3})", uscore.rank, uscore.formattedValue, Social.localUser.userName, uscore.userID);

                    ILeaderboard clb = Social.CreateLeaderboard ();
                    clb.id = leaderboardID;
                    clb.range = new Range (urank, numEitherSide * 2 + 1);

                    clb.LoadScores ((bool csuccess) =>
                    {
                        if (csuccess)
                        {
                            if (clb.scores.Length > 0)
                            {
                                string[] userIds = new string[clb.scores.Length];

                                for (int i = 0; i < clb.scores.Length; i++)
                                {
                                    IScore s = clb.scores[i];
                                    userIds[i] = s.userID;
                                }

                                Social.LoadUsers (userIds, (IUserProfile[] users) =>
                                {
                                    if (users != null && users.Length == clb.scores.Length)
                                    {
                                        for (int i = 0; i < clb.scores.Length; i++)
                                        {
                                            IScore s = clb.scores[i];
                                            output.AppendFormat ("{0}. {1} {2}{3}", s.rank, s.formattedValue, users[i].userName, i < clb.scores.Length - 1 ? "\n" : "");
                                        }
                                    }

                                    if (uiObj != null)
                                        callback (output.ToString ());

                                    Debug.Log (output.ToString ());
                                });
                            }
                        }
                        else
                            Debug.LogFormat ("Failed to load competitors");
                    });
                }
                else
                    Debug.LogFormat ("User {0} has not submitted a high score to leaderboard {1}", Social.localUser.userName, leaderboardID);
            }
            else
                Debug.LogError ("Failed to load user score");
        });
}
IterativeInteractive commented 5 years ago

I'm encountering the same issue, and I dug into the code a little bit.

Here's the relevant code in LoadScores in PlayGamesPlatform.cs:

           mClient.LoadScores(
                board.id,
                LeaderboardStart.PlayerCentered,
                board.range.count > 0 ? board.range.count : mClient.LeaderboardMaxResults(),
                board.userScope == UserScope.FriendsOnly ? LeaderboardCollection.Social : LeaderboardCollection.Public,
                timeSpan,
                (scoreData) => HandleLoadingScores(
(PlayGamesLeaderboard)board, scoreData, callback));

The starting point can only be LeaderboardStart.PlayerCentered or LeaderboardStart.TopScores. The range.from variable isn't even used in the entire plugin.

It's very disappointing how badly this plugin conforms to the ISocial interface. See also #2629 .

Would love to get an official reply for all these issues.

acakebread commented 4 years ago

yes, after extensive testing the range 'fromValue' parameter appears to make no difference whatsoever. The 'valueCount' parameter does however limit the returned array size to that amount.