Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaderboard Scores fail to update after first fetch / load. #1534

Open
Tehelee opened this issue Dec 25, 2016 · 44 comments
Open

Leaderboard Scores fail to update after first fetch / load. #1534

Tehelee opened this issue Dec 25, 2016 · 44 comments

Comments

@Tehelee
Copy link

Tehelee commented Dec 25, 2016

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.

@claywilkinson
Copy link

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.)

@Tehelee
Copy link
Author

Tehelee commented Dec 27, 2016

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

@claywilkinson
Copy link

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

@Tehelee
Copy link
Author

Tehelee commented Dec 27, 2016

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.

@claywilkinson
Copy link

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
Copy link

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!

@DutchGuerrillia
Copy link

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
Copy link

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

@zory
Copy link

zory commented Feb 1, 2017

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.

@Mukikaizoku
Copy link
Contributor

@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?

@zory
Copy link

zory commented Feb 15, 2017

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

@asadrana91
Copy link

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?

@zory
Copy link

zory commented Feb 21, 2017

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.

@Mukikaizoku
Copy link
Contributor

@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?

@Firemaw
Copy link

Firemaw commented May 17, 2017

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.

@jeffries7
Copy link

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.

@Firemaw
Copy link

Firemaw commented Jul 26, 2017

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");
  }
);

@jeffries7
Copy link

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.

@Firemaw
Copy link

Firemaw commented Jul 26, 2017

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.

@BlueSpiritbox
Copy link

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.

@Mokalipilou
Copy link

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?

@jeffries7
Copy link

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

@JDeuce
Copy link

JDeuce commented Apr 19, 2018

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

@itsdrew
Copy link

itsdrew commented Apr 30, 2018

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.

@Majter
Copy link

Majter commented May 17, 2018

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.

@mgrogin
Copy link

mgrogin commented Jul 8, 2018

@itsdrew how do you flush the cache?

@itsdrew
Copy link

itsdrew commented Jul 8, 2018

@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.

@mgrogin
Copy link

mgrogin commented Jul 8, 2018

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 :)

@YiorgosX
Copy link

YiorgosX commented Jan 2, 2019

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?

@ignacevau
Copy link

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.

@AMastryukov
Copy link

AMastryukov commented Apr 2, 2019

This issue persists for me as well. I verify that my scores are successfully reported and then check the leaderboard by calling PlayGamesPlatform.Instance.LoadScores() with TopScores and then PlayGamesPlatform.Instance.ShowLeaderboardUI() if the data returned from LoadScores() is valid. The scores update sometimes but most times they do not. I have used @itsdrew's solution by changing the plugin to use NETWORK_ONLY.

I'm investigating how tamper protection for scores might affect this (it's enabled in Google Play Services console by default).

UPDATE: I believe I have managed to resolve the issue by ensuring that PlayGamesPlatform is only initialized once at the start of the application. I made an in-depth guide for this here (timestamp for the issue itself): https://www.youtube.com/watch?v=0LGs1Xtt_1I&t=504. Also, do not report scores too often (I have not tested how often is too often, but once every minute or so seems to be good enough).

@CatalystJesal
Copy link

I can also confirm that I'm having trouble getting the leaderboard to update correctly. There has been cases where stale scores have been shown (via cache) and further additional records of new player scores not showing up. When I look into my app on the Google Play Console and navigate to the Leaderboard, it shows I have 7 unique entries, however the app only shows 5 and updates those scores, sometimes certain scores will update and other times they won't....I use the PlayGamesPlatform.Instance.ShowLeaderboardUI() to show the leaderboard. This has also been an issue during testing.

Google Play Services plugin version: 0.9.64

@kcheeb
Copy link

kcheeb commented Aug 11, 2019

unbelievable google still didnt address this issue

@kcheeb
Copy link

kcheeb commented Aug 11, 2019

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

got

Assets\GooglePlayGames\Platforms\Native\PInvoke\LeaderboardManager.cs(93,4): error CS0246: The type or namespace name 'DataSourceType' could not be found (are you missing a using directive or an assembly reference?)

So I changed DataSourceType to simply DataSource, but then

Assets\GooglePlayGames\ISocialPlatform\PlayGamesPlatform.cs(46,38): error CS0535: 'PlayGamesPlatform' does not implement interface member 'ISocialPlatform.LoadScores(string, Action<IScore[]>)'

So i put Types.DataSource instead, but then

Assets\GooglePlayGames\ISocialPlatform\PlayGamesPlatform.cs(1046,5): error CS0119: 'Types.DataSource' is a type, which is not valid in the given context

So i put Types.DataSource.NETWORK_ONLY

Assets\GooglePlayGames\ISocialPlatform\PlayGamesPlatform.cs(1046,5): error CS1503: Argument 6: cannot convert from 'GooglePlayGames.Native.Cwrapper.Types.DataSource' to 'GooglePlayGames.BasicApi.DataSource'

I dont think what you wrote can be compiled at all. did you define this 'DataSourceType' somewhere else? where can this be imported from? can u pls post your PlayGamesPlatform.cs, IPlayGamesClient.cs, and others that you changed

@kcheeb
Copy link

kcheeb commented Aug 11, 2019

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?

I am testing on 3 devices. 2 of my devices can upload scores, while 1 cannot. This is extremely retarded

@NeuralEvolution
Copy link

I am having this exact same issue. It only happens as stated above with PlayerCentered scores. Why has this not been fixed it was opened in 2016. Is anyone from google even looking into this?

@ozdemir08 ozdemir08 added the bug label Dec 31, 2019
@dipaninside
Copy link

Still the Plugin showing outdated data. Cant fix it to load from network. somebody help please.

@luizhm0reira
Copy link

Is this issue solved? Any update please?
thank you

@mura94
Copy link

mura94 commented Sep 23, 2020

Any updates on this? Running into the same problem.

@CoreyHendrey
Copy link

Just chiming in to say I'm running into the same problem.

@RafalWilkowski
Copy link

RafalWilkowski commented Nov 10, 2020

I'm working on GooglePlayGamesPlugin - 0.10.11 and ran into the same problem. I tried to get all-time rank and daily rank on the start screen of my game. All-time rank fetched well, but daily fetched good once and then read from cache old value. So to solve it you need as mention above use NETWORK only.

To do that you need to find AndroidClient.cs and method LoadScores(). Inside you find task:

using (var task = client.Call<AndroidJavaObject>(loadScoresMethod
,leaderboardId, AndroidJavaConverter.ToLeaderboardVariantTimeSpan(timeSpan), AndroidJavaConverter.ToLeaderboardVariantCollection(collection), rowCount))

After rowCount you need to add additional bool argument which FORCE to use NETWORK only so it should look like this:

using (var task = client.Call<AndroidJavaObject>(loadScoresMethod
,leaderboardId, AndroidJavaConverter.ToLeaderboardVariantTimeSpan(timeSpan), AndroidJavaConverter.ToLeaderboardVariantCollection(collection), rowCount, true))

Be aware, as mentioned in Google Documentation:
FORCE REALOAD - If true, this call will clear any locally cached data and attempt to fetch the latest data from the server. This would commonly be used for something like a user-initiated refresh. Normally, this should be set to false to gain advantages of data caching.
Also in best practices:
Use the client libraries. The mobile client libraries employ a number of strategies to reduce the calls you make to the service. For instance, data for achievements and leaderboards is cached, so players can view their achievements as often as they like without requiring the service to make multiple calls.

But I don't have a choice, it need to be reloaded every time :)

@LASpencer
Copy link

I'm seeing the same issue with v0.11.01
I've tried using the workaround above, editing the client to force it to reload from the network, but it doesn't work.

Viewing the leaderboards through the Google Play app shows the up to date score on both public and social leaderboards, but even if you delete the cache, getting the public leaderboard through the API doesn't return your score.

@rpinto-centi
Copy link

rpinto-centi commented Sep 26, 2022

any update?
i have the same issue

@256p
Copy link

256p commented Oct 26, 2022

I've tried using the workaround above, editing the client to force it to reload from the network, but it doesn't work.

Actually, it helped me. In v0.11.01 in AndroidClient.cs I have added true argument for forceReload in LoadScores function on line 794. It looks like the problem is not in the unity plugin but in the android game services library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests