Разработка системы лидербордов мобильной игры
Лидерборды — социальный механизм, который превращает одиночный прогресс в соревнование. Для casual-игр достаточно простого глобального рейтинга. Для mid-core и competitive — нужны сегментированные лидерборды: среди друзей, по региону, еженедельный, по конкретному уровню. Разница в реализации — принципиальная.
Выбор бэкенда
| Решение | Когда подходит | Ограничения |
|---|---|---|
| Google Play Games Leaderboards | Простой глобальный рейтинг, Android | Только Android, ограниченные типы |
| Game Center Leaderboards | iOS, simple global/friends | Только iOS |
| PlayFab Leaderboards | Кросс-платформа, гибко | Платный при высокой нагрузке |
| Firebase Realtime DB / Firestore | Гибко, real-time | Нужна кастомная индексация |
| Custom backend | Полный контроль | Разработка и поддержка |
Для большинства мобильных игр PlayFab — оптимальный выбор: не нужно писать серверную логику, есть встроенный anti-cheat для очков.
PlayFab Leaderboards
// Запись очков
public void SubmitScore(int score, string leaderboardName = "global_score")
{
PlayFabClientAPI.UpdatePlayerStatistics(
new UpdatePlayerStatisticsRequest
{
Statistics = new List<StatisticUpdate>
{
new StatisticUpdate
{
StatisticName = leaderboardName,
Value = score
}
}
},
result => Debug.Log("Score submitted"),
error => Debug.LogError(error.GenerateErrorReport())
);
}
// Получение топ-100
public void GetLeaderboard(string leaderboardName, Action<List<LeaderboardEntry>> callback)
{
PlayFabClientAPI.GetLeaderboard(
new GetLeaderboardRequest
{
StatisticName = leaderboardName,
StartPosition = 0,
MaxResultsCount = 100,
ProfileConstraints = new PlayerProfileViewConstraints
{
ShowDisplayName = true,
ShowAvatarUrl = true
}
},
result =>
{
var entries = result.Leaderboard.Select(entry => new LeaderboardEntry
{
PlayFabId = entry.PlayFabId,
DisplayName = entry.DisplayName,
Score = entry.StatValue,
Rank = entry.Position + 1,
AvatarUrl = entry.Profile?.AvatarUrl
}).ToList();
callback?.Invoke(entries);
},
error => Debug.LogError(error.GenerateErrorReport())
);
}
// Позиция текущего игрока
public void GetPlayerRank(string leaderboardName, Action<int> callback)
{
PlayFabClientAPI.GetLeaderboardAroundPlayer(
new GetLeaderboardAroundPlayerRequest
{
StatisticName = leaderboardName,
MaxResultsCount = 1
},
result =>
{
var playerEntry = result.Leaderboard.FirstOrDefault(e => e.PlayFabId == PlayFabSettings.staticPlayer.PlayFabId);
callback?.Invoke(playerEntry?.Position + 1 ?? 0);
},
error => { }
);
}
Сегментированные лидерборды
Еженедельный сброс — PlayFab поддерживает автоматический сброс статистики по расписанию. Настраивается в PlayFab Game Manager → Statistics → Reset interval. Weekly или Monthly.
Лидерборд среди друзей. PlayFab Friends API:
public void GetFriendsLeaderboard(string leaderboardName, Action<List<LeaderboardEntry>> callback)
{
PlayFabClientAPI.GetFriendLeaderboard(
new GetFriendLeaderboardRequest
{
StatisticName = leaderboardName,
StartPosition = 0,
MaxResultsCount = 50
},
result => { /* обработка */ },
error => { }
);
}
Лидерборд по уровню — нужен отдельный statistic для каждого уровня или использование версионирования статистики (Version-based leaderboards в PlayFab).
Антифрод и валидация очков
Клиентский score без валидации — это прямой путь к читерству через Memory Editor или Cheat Engine. Варианты защиты:
Серверный расчёт очков. Клиент отправляет события (убил врага, собрал предмет), сервер считает итоговый score. PlayFab Cloud Script:
handlers.EndLevel = function(args) {
var events = args.events; // события уровня
var calculatedScore = calculateScore(events); // серверный расчёт
server.UpdatePlayerStatistics({
PlayFabId: currentPlayerId,
Statistics: [{ StatisticName: "global_score", Value: calculatedScore }]
});
return { score: calculatedScore };
};
Плауз-чек. Если максимально возможный score за уровень длиной 3 минуты — 10 000, а игрок присылает 50 000 — запись отклоняется или помечается для ревью.
Google Play Games и Game Center
Для платформенных лидербордов, которые видны в интерфейсе магазина:
// Google Play Games v2 (через Unity SDK)
PlayGamesPlatform.Instance.ReportScore(
score,
GPGSIds.leaderboard_global_score,
success => Debug.Log($"Score reported: {success}")
);
PlayGamesPlatform.Instance.LoadScores(
GPGSIds.leaderboard_global_score,
LeaderboardStart.TopScores,
100,
LeaderboardCollection.Public,
LeaderboardTimeSpan.AllTime,
data => { /* data.Scores */ }
);
Платформенные лидерборды хороши для discovery — игрок видит рейтинг прямо в Google Play без запуска игры. Но ограниченный контроль над дизайном и нет cross-platform.
UI-паттерны
Хороший лидерборд отображает:
- Позицию и очки текущего игрока всегда видимы (закреплены вверху или внизу)
- Игроки вокруг текущего (±5 позиций) — GetLeaderboardAroundPlayer
- Топ-3 выделены визуально
- Аватары (из PlayFab Profile или платформенного аккаунта)
Пагинация или бесконечный скролл с GetLeaderboard(startPosition: offset) — для доступа к нижним строкам.
Что входит в работу
- Настройка PlayFab Statistics с нужными именами и правилами сброса
- Реализация submit, get top, get around player
- Лидерборд среди друзей
- Серверная валидация очков (Cloud Script)
- Платформенная интеграция (Google Play Games / Game Center)
- UI: список, позиция игрока, аватары, фильтры (global/friends/weekly)
Сроки
Глобальный лидерборд на PlayFab: 2–4 дня. Полная система с сегментацией, серверной валидацией и UI: 1–2 недели. Стоимость рассчитывается индивидуально.







