坑1:排行榜无法一次拉取100大量数据。
解决方案:原因是谷歌排行榜LoadScores每次最多只能获取30条数据。下文附带的接口GetTop100UserDic可以解决问题,他可以直接拉取到Top一百数据,如有其他数量需求可对其进行修改。
坑2:showleaderboardui can only be called after authentication等类似权限报错或警告
解决方案:一共分两种情况。一种是用户需要在Google Play上公开自己的数据,另一种是需要在谷歌开发者账号发布排行榜。对于用户公开数据,建议检查应用设置并确保允许公开数据,并在应用代码中正确处理和访问用户数据。对于发布排行榜,请检查开发者账号设置并设置相关的排行榜信息,然后根据谷歌的文档和指南,在应用中实现排行榜功能。
坑3:想获取玩家在每周排行榜中排名,但只能返回历史排名。
解决方案:
- 打开AndroidClient.cs文件,可以使用任何文本编辑器或集成开发环境(IDE)进行编辑。
- 根据下文提供的图像和代码,在适当的位置进行修改。
- 确保修改后的代码逻辑正确,并进行测试以验证其功能。
using (var leaderboard = leaderboardScoresJava.Call<AndroidJavaObject>("getLeaderboard"))
{
using (var variants = leaderboard.Call<AndroidJavaObject>("getVariants"))
{
var arrayListIterator = variants.Call<AndroidJavaObject>("iterator");
while (arrayListIterator.Call<bool>("hasNext"))
{
using (var variant = arrayListIterator.Call<AndroidJavaObject>("next"))
{
if (variant.Call<int>("getCollection") == (int)collection - 1 && variant.Call<int>("getTimeSpan") == (int)timespan - 1)
{
leaderboardScoreData.Title = leaderboard.Call<string>("getDisplayName");
if (variant.Call<bool>("hasPlayerInfo"))
{
var date = AndroidJavaConverter.ToDateTime(0);
var rank = (ulong)variant.Call<long>("getPlayerRank");
var score = (ulong)variant.Call<long>("getRawPlayerScore");
var metadata = variant.Call<string>("getPlayerScoreTag");
leaderboardScoreData.PlayerScore = new PlayGamesScore(date, leaderboardId,
rank, mUser.id, score, metadata);
}
leaderboardScoreData.ApproximateCount = (ulong)variant.Call<long>("getNumScores");
}
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using UnityEngine;
using UnityEngine.SocialPlatforms;
using Utils;
public class SocialManager : MonoBehaviour
{
public static string UserName { get; private set; }
public static string UserID { get; private set; }
public static bool IsLogin { get; private set; }
#if UNITY_ANDROID
private static Action<SignInStatus> result;
/// <summary>
/// 自动登录(静默)
/// </summary>
/// <param name="_result"></param>
public static void AutoLoginIn(Action<SignInStatus> _result = null)
{
if (IsLogin)
{
_result?.Invoke(SignInStatus.Success);
return;
}
result = _result;
PlayGamesPlatform.Activate();
PlayGamesPlatform.Instance.Authenticate(ProcessAuthentication);
}
/// <summary>
/// 手动登录(非静默登录)
/// </summary>
/// <param name="_result"></param>
public static void ManuallyLogin(Action<SignInStatus> _result = null)
{
if (IsLogin)
{
_result?.Invoke(SignInStatus.Success);
return;
}
result = _result;
PlayGamesPlatform.Instance.ManuallyAuthenticate(ProcessAuthentication);
}
private static void ProcessAuthentication(SignInStatus status)
{
IsLogin = status == SignInStatus.Success;
result?.Invoke(status);
if (status == SignInStatus.Success)
{
UserName = PlayGamesPlatform.Instance.localUser.userName;
UserID = PlayGamesPlatform.Instance.localUser.id;
Debug.Log("Authentication Success");
Debug.Log("user id = " + UserID);
Debug.Log("user name = " + UserName);
// Continue with Play Games Services
}
else
{
Debug.Log("Authentication Failed : " + status);
}
}
/// <summary>
/// 展示谷歌排行面板
/// </summary>
/// <param name="rankName"></param>
public static void ShowRankUI(string rankName)
{
PlayGamesPlatform.Instance.ShowLeaderboardUI(rankName);
}
/// <summary>
/// 上传分数
/// </summary>
/// <param name="_score"></param>
/// <param name="_result"></param>
public static void UploadScore(string rankName, long _score, string _metadata, Action<bool> _result = null)
{
if (!IsLogin)
{
_result?.Invoke(false);
return;
}
PlayGamesPlatform.Instance.ReportScore(_score, rankName, _metadata, (bool success) =>
{
_result?.Invoke(success);
if (success)
{
Debug.Log("分数上传成功!");
}
else
{
Debug.Log("分数上传失败!");
}
});
}
public static bool ScoreIsVaild(PlayGamesScore score)
{
if (!string.IsNullOrEmpty(score.metaData))
{
if (long.TryParse(score.metaData, out long r))
{
DateTime date = r.ToDateTimeRank();
return DateTime.UtcNow <= date;
}
}
return true;
}
/// <summary>
/// 获取排行榜数据
/// </summary>
/// <param name="start">起点</param>
/// <param name="rowCount">数目</param>
/// <param name="collection">集合</param>
/// <param name="timeSpan">周期</param>
/// <param name="_result"></param>
public static void GetLeaderboardUserDic(string rankName, LeaderboardStart start = LeaderboardStart.TopScores, int rowCount = 100, LeaderboardCollection collection = LeaderboardCollection.Public, LeaderboardTimeSpan timeSpan = LeaderboardTimeSpan.Weekly, Action<Dictionary<PlayGamesUserProfile, IScore>> _result = null)
{
GetLeaderboardData(rankName, start, rowCount, collection, timeSpan, (data) =>
{
LoadUsersAndDisplay(data, _result);
});
}
/// <summary>
/// 获取排行榜Top100数据
/// </summary>
/// <param name="rankName"></param>
/// <param name="timeSpan"></param>
/// <param name="_result"></param>
public static void GetTop100UserDic(string rankName, LeaderboardTimeSpan timeSpan = LeaderboardTimeSpan.Weekly, Action<Dictionary<PlayGamesUserProfile, IScore>> _result = null)
{
GetTop100UserDic(rankName, timeSpan, (data) =>
{
LoadUsersAndDisplay(data, _result);
});
}
/// <summary>
/// 获取排行榜中自己的数据
/// </summary>
/// <param name="collection"></param>
/// <param name="timeSpan"></param>
/// <param name="_result"></param>
public static void GetLeaderboardMyScore(string rankName, LeaderboardCollection collection = LeaderboardCollection.Public, LeaderboardTimeSpan timeSpan = LeaderboardTimeSpan.Weekly, Action<PlayGamesScore, ulong> _result = null)
{
GetLeaderboardData(rankName, LeaderboardStart.TopScores, 1, collection, timeSpan, (data) =>
{
if (data.PlayerScore != null)
{
_result?.Invoke(data.PlayerScore as PlayGamesScore, data.ApproximateCount);
}
else
{
_result?.Invoke(null, 0);
}
});
}
/// <summary>
/// 获取排行榜玩家附近数据
/// </summary>
/// <param name="rankName"></param>
/// <param name="timeSpan"></param>
/// <param name="_result"></param>
public static void GetLeaderboardNear(string rankName, LeaderboardTimeSpan timeSpan, Action<Dictionary<PlayGamesUserProfile, IScore>> _result = null)
{
GetLeaderboardData(rankName, LeaderboardStart.PlayerCentered, 1, LeaderboardCollection.Public, timeSpan, (data) =>
{
LoadUsersAndDisplay(data, _result);
});
}
private static void GetLeaderboardData(string rankName, LeaderboardStart start = LeaderboardStart.TopScores, int rowCount = 30, LeaderboardCollection collection = LeaderboardCollection.Public, LeaderboardTimeSpan timeSpan = LeaderboardTimeSpan.Weekly, Action<LeaderboardScoreData> _result = null)
{
PlayGamesPlatform.Instance.LoadScores(
rankName,
start,
rowCount,
collection,
timeSpan,
(data) =>
{
_result?.Invoke(data);
if (data != null)
{
Debug.Log("Leaderboard data valid: " + data.Valid);
if (data.Scores != null)
{
Debug.Log("approx:" + data.ApproximateCount + " have " + data.Scores.Length);
}
if (data.PlayerScore != null)
{
Debug.Log("player score: " + data.PlayerScore.value);
Debug.Log("player rank: " + data.PlayerScore.rank);
int t = (int)data.ApproximateCount;
float v = ((float)(t - data.PlayerScore.rank)) / t;
Debug.Log(string.Format("You've surpassed {0} percent of the players.", (int)(v * 100)));
}
}
});
}
private static void GetTop100UserDic(string rankName, LeaderboardTimeSpan timeSpan = LeaderboardTimeSpan.Weekly, Action<LeaderboardScoreData> _result = null)
{
List<LeaderboardScoreData> allScores = new List<LeaderboardScoreData>();
void action(LeaderboardScoreData data)
{
allScores.Add(data);
if (allScores.Count < 100 && data.NextPageToken != null && data.Scores.Length >= 20)
{
PlayGamesPlatform.Instance.LoadMoreScores(data.NextPageToken, 20, (data) => { action(data); });
}
else
{
_result?.Invoke(data);
if (data != null)
{
Debug.Log("Leaderboard data valid: " + data.Valid);
if (data.Scores != null)
{
Debug.Log("approx:" + data.ApproximateCount + " have " + data.Scores.Length);
}
if (data.PlayerScore != null)
{
Debug.Log("player score: " + data.PlayerScore.value);
Debug.Log("player rank: " + data.PlayerScore.rank);
int t = (int)data.ApproximateCount;
float v = ((float)(t - data.PlayerScore.rank)) / t;
Debug.Log(string.Format("You've surpassed {0} percent of the players.", (int)(v * 100)));
}
}
}
}
PlayGamesPlatform.Instance.LoadScores(
rankName,
LeaderboardStart.TopScores,
20,
LeaderboardCollection.Public,
timeSpan,
action);
}
private static void LoadUsersAndDisplay(LeaderboardScoreData _data, Action<Dictionary<PlayGamesUserProfile, IScore>> _result = null)
{
// get the user ids
List<string> userIds = new List<string>();
foreach (IScore score in _data.Scores)
{
userIds.Add(score.userID);
}
// load the profiles and display (or in this case, log)
PlayGamesPlatform.Instance.LoadUsers(userIds.ToArray(), (users) =>
{
Dictionary<PlayGamesUserProfile, IScore> rank_user_dic = new Dictionary<PlayGamesUserProfile, IScore>();
string status = "Leaderboard loading: " + _data.Title + " count = " +
_data.Scores.Length;
foreach (IScore score in _data.Scores)
{
PlayGamesUserProfile user = FindUser(users, score.userID);
rank_user_dic.Add(user, score);
status += "\n" + score.formattedValue + " by " +
(string)(
(user != null) ? user.userName : "**unk_" + score.userID + "**");
}
_result?.Invoke(rank_user_dic);
Debug.Log(status);
});
}
private static PlayGamesUserProfile FindUser(IUserProfile[] users, string userid)
{
foreach (PlayGamesUserProfile user in users)
{
if (user.id == userid)
{
return user;
}
}
return null;
}
#endif
}