Añadir logros y tablas de clasificación a tu juego móvil
Cómo utilizar el plugin games_services para añadir funcionalidad a tu juego.
Los jugadores tienen diversas motivaciones para jugar. A grandes rasgos, existen cuatro motivaciones principales: inmersión, logro, cooperación y competición. No importa el juego que construyas, algunos jugadores quieren obtener logros en él. Esto podría ser trofeos ganados o secretos desbloqueados. Algunos jugadores quieren competir en él. Esto podría ser alcanzar puntuaciones altas o realizar speedruns. Estas dos ideas se corresponden con los conceptos de logros y tablas de clasificación.
Los ecosistemas como App Store y Google Play proporcionan servicios centralizados para logros y tablas de clasificación. Los jugadores pueden ver los logros de todos sus juegos en un solo lugar y los desarrolladores no necesitan volver a implementarlos para cada juego.
Esta receta demuestra cómo usar el paquete games_services
para añadir funcionalidad de logros y tablas de clasificación a tu juego móvil.
1. Habilitar servicios de plataforma
#Para habilitar los servicios de juegos, configura Game Center en iOS y Google Play Games Services en Android.
iOS
#Para habilitar Game Center (GameKit) en iOS:
-
Abre tu proyecto de Flutter en Xcode. Abre
ios/Runner.xcworkspace Selecciona el proyecto raíz Runner.
Ve a la pestaña Signing & Capabilities.
Haz clic en el botón
+para añadir Game Center como una capacidad.Cierra Xcode.
-
Si aún no lo has hecho, registra tu juego en App Store Connect y, desde la sección My App, presiona el icono
+.
-
Aún en App Store Connect, busca la sección Game Center. Puedes encontrarla en Services al momento de escribir esto. En la página de Game Center, es posible que quieras configurar una tabla de clasificación y varios logros, dependiendo de tu juego. Toma nota de los IDs de las tablas de clasificación y los logros que crees.
Android
#Para habilitar Play Games Services en Android:
-
Si aún no lo has hecho, ve a Google Play Console y registra tu juego allí.

-
Aún en Google Play Console, selecciona Play Games Services → Setup and management → Configuration en el menú de navegación y sigue sus instrucciones.
Esto requiere una cantidad significativa de tiempo y paciencia. Entre otras cosas, tendrás que configurar una pantalla de consentimiento de OAuth en Google Cloud Console. Si en algún momento te sientes perdido, consulta la guía oficial de Play Games Services.

-
Cuando termines, puedes empezar a añadir tablas de clasificación y logros en Play Games Services → Setup and management. Crea exactamente el mismo conjunto que hiciste en el lado de iOS. Toma nota de los IDs.
Ve a Play Games Services → Setup and management → Publishing.
-
Haz clic en Publish. No te preocupes, esto no publica realmente tu juego. Solo publica los logros y la tabla de clasificación. Una vez que una tabla de clasificación, por ejemplo, se publica de esta manera, no se puede despublicar.
-
Ve a Play Games Services → Setup and management → Configuration → Credentials.
-
Busca el botón Get resources. Devuelve un archivo XML con los IDs de Play Games Services.
xml<!-- THIS IS JUST AN EXAMPLE --> <?xml version="1.0" encoding="utf-8"?> <resources> <!--app_id--> <string name="app_id" translatable="false">424242424242</string> <!--package_name--> <string name="package_name" translatable="false">dev.flutter.tictactoe</string> <!--achievement First win--> <string name="achievement_first_win" translatable="false">sOmEiDsTrInG</string> <!--leaderboard Highest Score--> <string name="leaderboard_highest_score" translatable="false">sOmEiDsTrInG</string> </resources> -
Añade un archivo en
android/app/src/main/res/values/games-ids.xmlque contenga el XML que recibiste en el paso anterior.
2. Iniciar sesión en el servicio de juego
#Ahora que has configurado Game Center y Play Games Services, y tienes listos tus IDs de logros y tablas de clasificación, finalmente es hora de Dart.
-
Añade una dependencia del paquete
games_services.flutter pub add games_services -
Antes de que puedas hacer cualquier otra cosa, tienes que iniciar la sesión del jugador en el servicio de juego.
darttry { await GamesServices.signIn(); } on PlatformException catch (e) { // ... deal with failures ... }
El inicio de sesión ocurre en segundo plano. Toma varios segundos, así que
no llames a signIn() antes de runApp() o los jugadores se verán obligados a
mirar una pantalla en blanco cada vez que inicien tu juego.
Las llamadas a la API de games_services pueden fallar por una multitud de
razones. Por lo tanto, cada llamada debe envolverse en un bloque try-catch como
en el ejemplo anterior. El resto de esta receta omite el manejo de
excepciones para mayor claridad.
3. Desbloquear logros
#-
Registra logros en Google Play Console y App Store Connect, y toma nota de sus IDs. Ahora puedes otorgar cualquiera de esos logros desde tu código Dart:
dartawait GamesServices.unlock( achievement: Achievement( androidID: 'your android id', iOSID: 'your ios id', ), );La cuenta del jugador en Google Play Games o Apple Game Center ahora enumera el logro.
-
Para mostrar la UI de logros desde tu juego, llama a la API de
games_services:dartawait GamesServices.showAchievements();Esto muestra la UI de logros de la plataforma como una superposición en tu juego.
-
Para mostrar los logros en tu propia UI, usa
GamesServices.loadAchievements().
4. Enviar puntuaciones
#Cuando el jugador termina una partida, tu juego puede enviar el resultado de esa sesión de juego a una o más tablas de clasificación.
Por ejemplo, un juego de plataformas como Super Mario puede enviar tanto la puntuación final como el tiempo transcurrido para completar el nivel, a dos tablas de clasificación distintas.
-
En el primer paso, registraste una tabla de clasificación en Google Play Console y App Store Connect, y tomaste nota de su ID. Usando este ID, puedes enviar nuevas puntuaciones para el jugador:
dartawait GamesServices.submitScore( score: Score( iOSLeaderboardID: 'some_id_from_app_store', androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', value: 100, ), );No necesitas comprobar si la nueva puntuación es la más alta del jugador. Los servicios de juego de la plataforma se encargan de eso por ti.
-
Para mostrar la tabla de clasificación como una superposición sobre tu juego, realiza la siguiente llamada:
dartawait GamesServices.showLeaderboards( iOSLeaderboardID: 'some_id_from_app_store', androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', ); -
Si deseas mostrar las puntuaciones de la tabla de clasificación en tu propia UI, puedes obtenerlas con
GamesServices.loadLeaderboardScores().
5. Siguientes pasos
#Hay más en el plugin games_services. Con este plugin, puedes:
- Obtener el icono, nombre o ID único del jugador
- Guardar y cargar estados del juego
- Cerrar sesión en el servicio de juego
Algunos logros pueden ser incrementales. Por ejemplo: "Has recolectado las 10 piezas del McGuffin."
Cada juego tiene diferentes necesidades de los servicios de juego.
Para empezar, es posible que quieras crear este controlador para mantener toda la lógica de logros y tablas de clasificación en un solo lugar:
import 'dart:async';
import 'package:games_services/games_services.dart';
import 'package:logging/logging.dart';
/// Allows awarding achievements and leaderboard scores,
/// and also showing the platforms' UI overlays for achievements
/// and leaderboards.
///
/// A facade of `package:games_services`.
class GamesServicesController {
static final Logger _log = Logger('GamesServicesController');
final Completer<bool> _signedInCompleter = Completer();
Future<bool> get signedIn => _signedInCompleter.future;
/// Unlocks an achievement on Game Center / Play Games.
///
/// You must provide the achievement ids via the [iOS] and [android]
/// parameters.
///
/// Does nothing when the game isn't signed into the underlying
/// games service.
Future<void> awardAchievement({
required String iOS,
required String android,
}) async {
if (!await signedIn) {
_log.warning('Trying to award achievement when not logged in.');
return;
}
try {
await GamesServices.unlock(
achievement: Achievement(androidID: android, iOSID: iOS),
);
} catch (e) {
_log.severe('Cannot award achievement: $e');
}
}
/// Signs into the underlying games service.
Future<void> initialize() async {
try {
await GamesServices.signIn();
// The API is unclear so we're checking to be sure. The above call
// returns a String, not a boolean, and there's no documentation
// as to whether every non-error result means we're safely signed in.
final signedIn = await GamesServices.isSignedIn;
_signedInCompleter.complete(signedIn);
} catch (e) {
_log.severe('Cannot log into GamesServices: $e');
_signedInCompleter.complete(false);
}
}
/// Launches the platform's UI overlay with achievements.
Future<void> showAchievements() async {
if (!await signedIn) {
_log.severe('Trying to show achievements when not logged in.');
return;
}
try {
await GamesServices.showAchievements();
} catch (e) {
_log.severe('Cannot show achievements: $e');
}
}
/// Launches the platform's UI overlay with leaderboard(s).
Future<void> showLeaderboard() async {
if (!await signedIn) {
_log.severe('Trying to show leaderboard when not logged in.');
return;
}
try {
await GamesServices.showLeaderboards(
// TODO: When ready, change both these leaderboard IDs.
iOSLeaderboardID: 'some_id_from_app_store',
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy',
);
} catch (e) {
_log.severe('Cannot show leaderboard: $e');
}
}
/// Submits [score] to the leaderboard.
Future<void> submitLeaderboardScore(int score) async {
if (!await signedIn) {
_log.warning('Trying to submit leaderboard when not logged in.');
return;
}
_log.info('Submitting $score to leaderboard.');
try {
await GamesServices.submitScore(
score: Score(
// TODO: When ready, change these leaderboard IDs.
iOSLeaderboardID: 'some_id_from_app_store',
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy',
value: score,
),
);
} catch (e) {
_log.severe('Cannot submit leaderboard score: $e');
}
}
}
Más información
#El Flutter Casual Games Toolkit incluye las siguientes plantillas:
- basic: juego de inicio básico
- card: juego de cartas de inicio
- endless runner: juego de inicio (usando Flame) donde el jugador corre sin fin, esquivando obstáculos y obteniendo recompensas
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.