play-games-plugin-for-unity icon indicating copy to clipboard operation
play-games-plugin-for-unity copied to clipboard

Leaderboard Scores fail to update after first fetch / load.

Open SeraEris opened this issue 7 years ago • 43 comments

Steps to reproduce:

  1. Use Social.ReportScore() to upload a score
  2. Use any method to fetch / load scores, such as PlayGamesPlatform.Instance.LoadScores()
  3. Use Social.ReportScore() to upload a larger (better) score (or smaller depending on your leaderboard setting)
  4. Use any method to fetch / load scores, such as PlayGamesPlatform.Instance.LoadScores()

The score will not change, however if you use Social.ShowLeaderboardUI() the score listed will be updated.

Notes: The IScore 'PlayerScore' returned in the LeaderboardScoreData object from PlayGamesPlatform.Instance.LoadScores() will have the updated value, contrary to the value(s) reported in the IScore array 'Scores' of that same LeaderboardScoreData object.

The values loaded from LeaderboardCollection.Public and LeaderboardCollection.Social are seperate and both will load once initially. If you first use Public, then update the score, Public will still show the old value,. However Social will do its first fetch and find the updated score, then never update again.

I have tried every combination I can think of to troubleshoot and / or work around; I have narrowed the issue down to this plugin as demonstrated by the updated score in Social.ShowLeaderboardUI(). Somehow the value is being cached even through data / cache wipes and reinstalls.

@hak - I think this is a serious issue that should be resolved asap, thanks for all the work you've done so far.

SeraEris avatar Dec 25 '16 15:12 SeraEris

Thanks for the detailed debugging steps. I'll pass along the information. At a high level, is it accurate to say that the loadScores does not return updated scores until ShowLeaderboardUI is called? (And your "Notes" section is identifying the various caches.)

claywilkinson avatar Dec 27 '16 18:12 claywilkinson

LoadScores will fail to return updated scores at all, even after calling ShowLeaderboardUI.

After more debugging, it appears this is a PlayerCentered issue. LoadScores will fetch updated scores if LeaderboardStart is TopScores rather than PlayerCentered.

Thanks for the response Clay

SeraEris avatar Dec 27 '16 18:12 SeraEris

Thanks for the clarification! I'll pass it along.

claywilkinson avatar Dec 27 '16 19:12 claywilkinson

Using any configuration of the ILeaderboard object created from PlayGamesPlatform.Instance.CreateLeaderboard() also results in incorrect scores. As usual the localUserScore is updated, but the user's score in the IScore array contains the wrong value.

SeraEris avatar Dec 27 '16 19:12 SeraEris

I am looking into this today. Once thing that you might want to hack to see if makes a difference is to change LeaderboardManager.LoadLeaderboardData() to use Types.DataSource.NETWORK_ONLY vs. CACHE_OR_NETWORK. Also, to look at the result code returned to see if it is VALID or VALID_STALE.

I'll update the thread after I try this as well.

claywilkinson avatar Jan 03 '17 22:01 claywilkinson

I was able to reproduce the issue and passed along the information to the engineering team. I'll update the thread when I know more. Thanks again for your debugging!

claywilkinson avatar Jan 03 '17 22:01 claywilkinson

Yep, 'just want to let you know I'm facing the same problems :( Please fix this issue. I guess this has something to do with new leaderboards. Because lots of developers used the Play services in their games..

Cheers, Maarten

DutchGuerrillia avatar Jan 21 '17 13:01 DutchGuerrillia

Hello Tehelee,

I solved the problem for me. I did a few things, but the thing I suspect that did the trick is changing the following parameter:

PlayGamesPlatform.Instance.LoadScores( gPGSIds, LeaderboardStart.TopScores, recordsTotal, LeaderboardCollection.Public, leaderboardTimeSpan, (data) => {}

You see after LeaderboardStart I changed to TopScores instead of PlayerCentered.

Now I can ad new scores.

I also changed the following, but I thing it has nothing to do with the solution:

  • Changed Unity game version
  • Put the Game play Services to production
  • Add a test button to request the google scoreboards interface. Opent that once, but add my wives Phone I didn't even thoughed that button...so...no..

Hope it helps,

Cheers, Maarten

DutchGuerrillia avatar Jan 23 '17 19:01 DutchGuerrillia

First I thought it was UserCentered bug as well, but after more debug'ing I came up with another theory.

It seems, that then one user sends score (but dont get scores himself) other player will not see this score. I tried playing with Types.DataSource.NETWORK_ONLY parameters, but there were always at least one case then score wouldn't update. If user who have sent score downloaded scores for himself (not sure if Types.DataSource matters, tried a lot variants), then other user will get good scores too.

My workaround: Right after posting score, try to download my score forceing to download it with NETWORK_ONLY. Social.ReportScore(score, leaderboardID, (bool success) => { if (success) { FetchFix(leaderboardID, 0); } }); And private static void FetchFix(string leaderboardID, int tryCounter) { PlayGamesPlatform.Instance.LoadScores(leaderboardID, LeaderboardStart.PlayerCentered, 1, LeaderboardCollection.Public, LeaderboardTimeSpan.AllTime, DataSourceType.NETWORK_ONLY, (LeaderboardScoreData data) => { if (data != null && (data.Status == ResponseStatus.InternalError || data.Status == ResponseStatus.Timeout) && tryCounter <= 5) { FetchFix(leaderboardID, ++tryCounter); } }); } It seems, this workaround works for me. If you will see some situation where it might be wrong, comment. Sorry, something happened with code formatting.

zory avatar Feb 01 '17 15:02 zory

@zory Thanks for the workaround, I'm trying to add it, but I'm a bit confused. I found the enum parameter DataSource.ReadNetworkOnly, but I don't see any overload for PlayGamesPlatform.Instance.LoadScores that takes it as a parameter. Could you perhaps give some more details?

Mukikaizoku avatar Feb 06 '17 00:02 Mukikaizoku

Sorry for late reply. Yes, there is no overloaded method, I added method with one more additional argument. So basically you can use code I pasted before just add following things:

PlayGamesPlatform.cs Add argument to LoadScores method DataSourceType dataSourceType, then pass it mClient.LoadScores(leaderboardId, start, rowCount, collection, timeSpan, dataSourceType, callback);

Also add or change IPlayGamesClient.cs LoadScores method accordingly and implement it in DummyClient and NativeClient: public void LoadScores(string leaderboardId, LeaderboardStart start, int rowCount, LeaderboardCollection collection, LeaderboardTimeSpan timeSpan, DataSourceType dataSourceType, Action<LeaderboardScoreData> callback) and pass it to to leaderboardManager in LoadLeaderboardData(.blah blah blah, dataSourceType, blah blah)

change Types.DataSource.NETWORK_ONLY to your value in LoadLeaderboardData (LeaderboardManager).

After every score posting we downloading one score, but i guess it is better than having out of sync leaderboards. Hope it helps

zory avatar Feb 15 '17 14:02 zory

i am having the same issue, leaderboard only updates the first time for a user , anyone found the solution? secondly i needed to ask, my game is still in testing phase, do we need to publish the game before? or it should work fine in testing phase?

asadrana91 avatar Feb 20 '17 10:02 asadrana91

It should work without publishing (after publishing certain things can't be changed!). You can try solution mentioned before. If it works, let us know.

zory avatar Feb 21 '17 16:02 zory

@zory Thanks for the additional details! My reply was late as well, just finally getting back to this issue..

Anyway, I implemented your workaround and I got it to work! I needed to do go a step further and modify LeaderboardManager.HandleFetch (), which is the callback passed to C.LeaderboardManager_Fetch () called in LeaderboardManager.LoadLeaderboardData (). Within HandleFetch (), I changed Types.DataSource.CACHE_OR_NETWORK to Types.DataSource.NETWORK_ONLY within C.LeaderboardManager_FetchScoreSummary().

@claywilkinson Along the lines with this workaround, should we be managing the DataSource type to limit the number of calls for fresh data?

Mukikaizoku avatar Apr 17 '17 06:04 Mukikaizoku

I can confirm having the same issue as original poster on 0.9.36 with Unity 5.5.3f1 and Android 6.0.1. Setting LeaderboardManager.LoadLeaderboardData() to use Types.DataSource.NETWORK_ONLY alone did not fix the issue for me. I also had to change it in two other places in the same file.

Firemaw avatar May 17 '17 04:05 Firemaw

Is anyone else still having this issue? I'm using Unity 5.6.2p1 along with Play Games 0.9.37 and leaderboard scores only return when the LeaderboardStart is set to TopScores.

If I set it to PlayerCentered it just returns 1 for every player.

jeffries7 avatar Jul 25 '17 14:07 jeffries7

I am using Unity 5.6.2f1 with GPGS 0.9.36 and the following code returns 5 players centered around the logged in user correctly:

string leaderboardID = "l123456";
PlayGamesPlatform.Instance.LoadScores (leaderboardID, LeaderboardStart.PlayerCentered, 5, LeaderboardCollection.Public, LeaderboardTimeSpan.AllTime, (LeaderboardScoreData lsd) =>
{
  if (lsd.Valid)
  {
    // Do work with lsd
  }
  else
  {
    Debug.Log ("Invalid or no data for competitors was returned - user may not have submitted a score yet");
  }
);

Firemaw avatar Jul 26 '17 03:07 Firemaw

Have you made any changes to Play Games Platform as i've take your example and I still get the same results. The only other thing is that my leaderboard status is "Ready to publish", but that shouldn't make a difference.

jeffries7 avatar Jul 26 '17 08:07 jeffries7

Yes I had to change some references to Types.DataSource.NETWORK_ONLY as in another post above, otherwise it would keep returning the old cached data.

Firemaw avatar Jul 26 '17 09:07 Firemaw

I'm having this issue as well with 0.9.50. It's not returning any scores if I called LoadScores() after I report a score. It works fine if I call it before reporting a score. I tried the suggested workarounds by changing Types.DataSource.CACHE_OR_NETWORK to Types.DataSource.NETWORK_ONLY and LeaderboardStart.PlayerCentered to TopScores, but no luck.

BlueSpiritbox avatar Mar 23 '18 15:03 BlueSpiritbox

Hi, do we have any way to fix this 15 month old problem without altering GPG plugin files, being exposed to problems on future plugin updates?

On side note, having a broken caching system will only encourage temporary fixes that will ultimately lead to more problems. Is a proper fix planned at any point?

Mokalipilou avatar Apr 09 '18 14:04 Mokalipilou

As far as i'm aware this is still an issue

jeffries7 avatar Apr 10 '18 07:04 jeffries7

I can also confirm this issue is impacting me on Unity 2017.4.1f1 with 0.9.50.

I am using leaderboard = Social.CreateLeaderboard() followed by leaderboard.LoadScores().

After submitting my first score, the leaderboard was able to fetch the data.

With subsequent updates to the score, it still successfully returns from the load but only my original score is returned. If I open the default android UI with Social.ShowLeaderboardUI() then I can see the score has been correctly updated with Android Game Services.

Exiting the application and restarting it makes no difference, it still continues to use the cache.

Switching to top scores does fix the issue

JDeuce avatar Apr 19 '18 14:04 JDeuce

Confirmed as well. I am on 2017.3.1f1 with 0.9.50. Attempting to fix. In LeaderboardManager.cs, in the HandleFetch method i've changed Types.DataSource.CACHE_OR_NETWORK to Types.DataSource.NETWORK_ONLY.

C.LeaderboardManager_FetchScoreSummary(mServices.AsHandle(), **Types.DataSource.NETWORK_ONLY,** token.LeaderboardId, (Types.LeaderboardTimeSpan)token.TimeSpan, (Types.LeaderboardCollection)token.Collection, InternalFetchSummaryCallback, Callbacks.ToIntPtr<FetchScoreSummaryResponse>((rsp) => HandleFetchScoreSummary(data, rsp, selfPlayerId, maxResults, token, callback), FetchScoreSummaryResponse.FromPointer) );

Hopefully that will work, will post back later after testing.

Edit......................

That seems to have done the trick. I only had to change it in that one spot.

Edit.....................

Another update... I spoke to a (much more experienced) friend of mine, he said it would be a better idea to flush the cache and then load the leaderboard rather than hardcoding it to always pull from network. So, I suppose this isn't a bug afterall, it's one of those undocumented type of things.

itsdrew avatar Apr 30 '18 16:04 itsdrew

Hello guys, I have this kind of problem and start to print some values to figure out what is going on. NOTE: (I did this without changing Types.DataSource)

PlayGamesPlatform.Instance.LoadScores( GPGSIds.leaderboard_leaders_in_smoketesting, LeaderboardStart.PlayerCentered, 100, LeaderboardCollection.Public, LeaderboardTimeSpan.AllTime, (data) => { Debug.Log( "Valid: " + data.Valid + "Status: " + data.Status + " playerScore: "+ data.PlayerScore.value + " : " + data.PlayerScore.formattedValue ); });

The player score stored in data.PlayerScore.value (callback of PlayGamesPlatform.Instance.LoadScores) was different than the one stored in data.Scores[indexOfCurrentPlayer].value

For me, the updated one was the stored in data.PlayerScore.value The value stored in data.Scores[indexOfCurrentPlayer].value was out of date (at least for the current user).

To me, the more important thing is to show the correct value to the current user. I hope this work for you.

Majter avatar May 17 '18 20:05 Majter

@itsdrew how do you flush the cache?

mgrogin avatar Jul 08 '18 07:07 mgrogin

@mgrogin

I'm assuming that theres a method build in to the sdk for it somewhere. Honestly, I had a hell of a time getting stuff to work correctly since debugging is a nightmare when you can't test from the editor.

I ended up leaving it as network only and just allow it to get the scores fresh every time a leaderboard needed to be loaded since there was no time that I needed caching. You get 50,000,000 free requests per day. With that many, I don't mind showing an up to date by the second leaderboard every time someone wants to see it. My newer solution for games i've worked on more recently is to only use GPGS for login.

However, if I wanted to do this the 'right' way, I would leave it on the network only setting and implement my own caching logic in order to have its inner workings be transparent. For instance, if I wanted to allow updates every 5 min, i'd have a get leaderboard method that (using a built in to unity caching method) calls the gpgs get leaderboard method, stores the result and timestamp in cache. Every time it gets called, it checks the timestamp from cache and if it's been 5 minutes, call the gpgs method again, if not, show the stored scores.

itsdrew avatar Jul 08 '18 11:07 itsdrew

Thanks for the quick response @itsdrew ! I see in GooglePlayGames.Native.Cwrapper.GameServices theres a function called GameServices_Flush. I'm just not sure how to use it :)

mgrogin avatar Jul 08 '18 13:07 mgrogin

I'm having the same issue, with a twist: some of my beta testers can constantly upload scores, some other cannot, at all. All using the same build, of course. Anyone has experienced this?

YiorgosX avatar Jan 02 '19 14:01 YiorgosX

I can confirm that this has issue has not been fixed yet. I'm using Unity 2018.2.11f1 with the plugin version 0.9.53. Using 'TopScores' returned the updated values, 'PlayerCentered' did not. Using the workaround of @itsdrew did the trick for me.

ignacevau avatar Feb 14 '19 20:02 ignacevau