10 Ekim 2026 Cumartesi

Google Play Games Prestasjoner i Mobilspill: Butikkpåvirkning, 2 000 XP-grensen og MonoGame-arkitektur




Google Play Games Prestasjoner i Mobilspill: Butikkpåvirkning, 2 000 XP-grensen og MonoGame-arkitektur

Når du har utviklet og publisert et mobilspill i butikken, begynner den virkelige utfordringen: å forvandle spillerens nysgjerrighet de første minuttene til langsiktig engasjement. Når spillere sitter igjen med en enkel "fullfør nivået, start neste"-sløyfe, setter trettheten til slutt inn—eller de lukker appen uten noensinne å oppdage halvparten av de dypere spillmekanikkene du har bygget.

Ved første øyekast kan Google Play Games Services (GPGS) Achievements-systemet se ut som ingenting annet enn en samling små merker. Når det er gjennomtenkt designet, blir det imidlertid en kraftig oppbevaringsmotor (retention engine) som guider spillerne gjennom hvert eneste lag av spillets mekanikker.

I denne tekniske artikkelen bryter vi ned hva prestasjoner faktisk utretter i Google Play-økosystemet, hvordan vi designet 79 unike prestasjoner under Googles strenge XP-regler for Blocked: Pixel Panzer, og hvordan vi konstruerte en asynkron MonoGame / C# batch-pipeline som forhindrer FPS-fall og Android ANR (Application Not Responding)-feil under intense arkadekamper.


1. Hvorfor er prestasjoner i Google Play Games viktige?

Integrering av Google Play Games-prestasjoner gir fire konkrete fordeler på tvers av både spillerpsykologi og butikkens ytelsesberegninger:

  1. Alternative mål og spillerbevaring (Day-7 / Day-30 Retention):
    Ikke alle spillere kan nå førsteplassen på den globale ledertavlen (leaderboard), men enhver spiller kan jobbe mot "Ødelegg 100 tårn" eller "Fullfør et nivå uten å ta skade." Trinnvise (inkrementelle) prestasjoner gir en konkret fremdriftslinje som beveger seg fremover for hver spilløkt.
  2. Naturlig opplæring i spillmekanikk (Implisitt Onboarding):
    Spillere holder seg ofte til standardvåpenet sitt og nøler med å eksperimentere. I Blocked: Pixel Panzer oppmuntrer belønninger for samtidig smelting av blokker med grønn syre-ammunisjon på ColorWheel eller kritiske treff med svart ammunisjon spillerne til å oppdage og mestre hver eneste elementære modus.
  3. Umiddelbar tilbakemelding og Google Play Gamer XP:
    Å se det offisielle Google Play Games-banneret gli ned fra toppen av skjermen midt i en intens kamp—og tjene XP mot sitt globale Google Play Gamer-nivå—gir spillerne en varig følelse av progresjon knyttet til operativsystemprofilen deres.
  4. Google Play-økosystem og kvalitetssignaler:
    Google Play Games Services V2 (PGS V2)-integrasjon gir Zero-Tap automatisk pålogging, sømløs kompatibilitet med Google Play Games on PC, og sterkere engasjementsignaler i "Spill"-fanen i Google Play Butikk.

Blocked: Pixel Panzer In-Game Achievement Unlock Toast
Det offisielle Google Play Games "Turret Buster I"-varselet som vises øverst på skjermen akkurat idet det 10. tårnet ødelegges under en kamp på Nivå 103 i Blocked: Pixel Panzer.


2. Google Play Console-regler: 2 000 XP-grensen og begrensningen på 10 000 trinn

Når du konfigurerer prestasjoner i Google Play Console, må du designe rundt tre strenge plattformbegrensninger:

  • Det absolutte taket på 2 000 XP (Hard Cap): Summen av alle prestasjonspoeng i et enkelt spill kan ikke overstige 2 000 XP. Hver enkelt prestasjon må tildele mellom 5 og 200 XP, i trinn på 5.
  • Grensen på 10 000 trinn for trinnvise prestasjoner: Kumulative tellerprestasjoner støtter maksimalt 10 000 trinn (steps) i Play Console.
  • Krav om Play Games Services V2: Google faser ut det eldre V1 SDK-et. Moderne Android-spill må bygges på Xamarin.GooglePlayServices.Games.V2 (PlayGamesSdk og PlayGames.GetAchievementsClient).

Designe en katalog med 79 prestasjoner i Blocked: Pixel Panzer

Ved å gå gjennom kjerneenhetene i spillet vårt (TurretBlock, FighterJet, EnemyRocket, ColorWheel, HydraRegenerationSkill, Season), strukturerte vi 79 prestasjoner på til sammen 1 995 / 2 000 XP fordelt på 6 hovedkategorier:

Kategori Eksempler på prestasjoner Type Mål / Mekanikk
Enemy Hunters Jet Hunter I–III, Sky Dominator, Turret Buster I–III, Siege Master Inkrementell Ødelegg 10, 100, 1 000 og 10 000 jagerfly, forsvarstårn og målsøkende raketter.
Block Destruction & Explosives Pioneer Breaker, Demolition Crew, Crusher Supreme, Pixel Obliterator, Chain Reaction Inkrementell / Standard Knus fra 1 000 til 10 000 blokker og detoner 5/25/50 mål i en enkelt dynamitteksplosjon.
ColorWheel & Weapon Mastery Prismatic Pilot, Acid Dissolver, Critical Striker, Power Blaster, Speedy Sprinter, Beam Vaporizer Inkrementell Smelt blokker med grønn syre-ammunisjon, oppnå svarte kritiske treff, avfyr røde kraftskudd, lasere og målsøkende missiler.
Stage & Boss Progression First Blood, Giant Slayer, Decimator, Speedrunner I–III Inkrementell / Standard Første fiendedrap, første Boss-seier og fullføring av nivåer på under 4 minutter.
Purist Challenges Untouchable, Clean Victory I–III, Purist Gladiator, Mono Specialist Inkrementell / Standard Beseir bosser og fullfør høye nivåer uten å ta skade eller uten å bruke ferdigheter.
Atmosphere, Supplies & Meta Storm Fighter, Retro Connoisseur, Gem Tycoon, Quad Spectrum, Audiophile, Loyal Supporter Inkrementell / Skjult Ødelegg 100 tårn i regnvær, samle CRT-skjermer og lytt til hele spor i musikkspilleren.

For hver prestasjon opprettet vi tilpassede 512x512 pikselkunst-merkeikoner hvis rammer utvikler seg fra bronse til gull og prismatiske nivåer etter hvert som vanskelighetsgraden øker:

Blocked: Pixel Panzer Custom Achievement Badges
Seks eksempler på 512x512 merker fra vår katalog med 79 prestasjoner: Sky Dominator, Turret Buster III, Pixel Obliterator, Prismatic Pilot IV, Acid Dissolver II og Power Blaster II.

Eksperttips (Masseimport via ZIP): Å skrive inn 79 prestasjoner manuelt i nettgrensesnittet til Google Play Console tar timer. Bruk heller Play Consoles funksjon "Import achievements" ved å pakke AchievementsMetadata.csv, AchievementsIconsMappings.csv og dine 512x512 .jpg-ikoner i ett enkelt .zip-arkiv for å importere hele katalogen på sekunder.

Google Play Console Published Achievements Table
Vår tabell over publiserte prestasjoner og XP-fordeling i Google Play Console.


3. Ren arkitektur: IGamesService og AchievementDirector i delt kode

Blocked: Pixel Panzer er et flerplattforms MonoGame-prosjekt som kjører på både Windows PC (Microsoft Store) og Android (Google Play). For å holde vårt delte spillprosjekt (Blocked.Shared) helt fritt for Android SDK-avhengigheter, anvender vi prinsippet om avhengighetsinversjon (Dependency Inversion Principle - SOLID).

Først definerer vi en plattformuavhengig IGamesService-kontrakt i det delte laget:

namespace Blocked.Shared.Services
{
    public interface IGamesService
    {
        void Initialize();
        Task<bool> SignIn();
        Task<bool> IsAuthenticated();
        
        // Leaderboards
        void SubmitScore(string leaderboardId, long score);
        void ShowLeaderboards();
        void ShowLeaderboard(string leaderboardId);

        // Achievements
        void UnlockAchievement(string achievementId);
        void IncrementAchievement(string achievementId, int steps = 1);
        void ShowAchievements();
    }
}

I stedet for å spre prestasjonskontroller rundt i CollisionManager, GameplayScreen og Player, sentraliserer vi alle 79 regler i én enkelt koordinatorklasse, AchievementDirector:

public static class AchievementDirector
{
    public static void OnEnemyKilled(
        bool isJet = false,
        bool isTurret = false,
        bool isRocket = false,
        bool isBoss = false,
        Bullet? killingBullet = null,
        bool killedByLaser = false)
    {
        var gamesService = ScreenManager.Instance?.GamesService;
        if (gamesService == null) return; // Gjør trygt ingenting på Desktop PC-versjoner

        if (isTurret)
        {
            gamesService.IncrementAchievement(AchievementIds.TurretBuster1, 1);
            gamesService.IncrementAchievement(AchievementIds.TurretBuster2, 1);
            gamesService.IncrementAchievement(AchievementIds.TurretBuster3, 1);
            gamesService.IncrementAchievement(AchievementIds.SiegeMaster, 1);

            // Tårn ødelagt i regnvær gir fremgang mot "Storm Fighter"
            if (Season.Current == SeasonKind.Rainy)
            {
                gamesService.IncrementAchievement(AchievementIds.StormFighter, 1);
            }
        }

        TrackWeaponKill(gamesService, killingBullet, killedByLaser);
    }
}

4. Kritisk ingeniørarbeid: Eliminere JNI / Binder IPC-overhead for å forhindre ANR

I et fartsfylt arkadespill skaper direkte kobling av prestasjonstriggere til Google Play SDK en alvorlig ytelsesfelle:

Når en spiller detonerer en eksplosiv blokk (ExplosiveBlock) eller bruker ferdigheten laserstråle (Laser Beam), kan 20 til 30 blokker og fiender bli ødelagt innenfor en enkelt ramme (16,6 millisekunder). Når hver ødeleggelse oppdaterer 5 eller 6 trinnvise nivåer, kan en enkelt ramme utløse over 150 IncrementAchievement-kall!

Hvis du sender 150 synkrone JNI- og Binder IPC-kall til Google Play Services på hovedtråden i spillsløyfen:

  1. Innstegsmodeller av Android-enheter (telefoner med 1–2 GB RAM og Android Go) opplever umiddelbart alvorlige hakking i bildefrekvensen.
  2. JNI Global Reference (GREF)-tabellen fylles opp, noe som utløser ANR (Input dispatching timed out)-rapporter i Google Play Vitals.

Vår løsning: 1,5-sekunders batching i minnet og økt-deduplisering

Vår implementering i GooglePlayGamesService.cs isolerer MonoGame-oppdateringssløyfen fullstendig fra Google Play IPC-kall:

  1. Økt-deduplisering (_unlockedInSession):
    Når en standardprestasjon er låst opp i løpet av en økt, legges ID-en til i et HashSet<string>. Gjentatte triggere i samme eller påfølgende rammer returnerer umiddelbart i C# uten noen JNI-kostnad.
  2. 1,5-sekunders bakgrunnsbatching (_pendingIncrements):
    Å kalle IncrementAchievement øker ganske enkelt et heltall i en minnebasert Dictionary<string, int> på hovedtråden (null JNI-kall). En bakgrunnsarbeider via Task.Run våkner etter 1,5 sekunder, tar et øyeblikksbilde av de akkumulerte summene og sender dem til Google Play Services i ett samlet kall per prestasjon.
  3. Håndtering av 26502: CLIENT_RECONNECT_REQUIRED og frakoblet bufring:
    Hvis en spiller legger spillet i bakgrunnen i flere timer og kommer tilbake, kan Google Play-økttokenet utløpe og utløse feilen 26502 (CLIENT_RECONNECT_REQUIRED). Tjenesten vår fanger opp dette, forsøker en enkelt stillegående bakgrunns-SignIn() med en nedkjølingsbeskyttelse, og faller tilbake til GPGS' lokale frakoblede buffer (client.Unlock) hvis enheten er frakoblet—noe som sikrer at ingen spillerprestasjoner noensinne går tapt.
private static readonly HashSet<string> _unlockedInSession = new(StringComparer.Ordinal);
private static readonly Dictionary<string, int> _pendingIncrements = new(StringComparer.Ordinal);
private static readonly object _achievementBatchLock = new();
private static bool _incrementFlushScheduled = false;

public void IncrementAchievement(string achievementId, int steps = 1)
{
    if (!_isInitialized || string.IsNullOrEmpty(achievementId) || steps <= 0)
        return;

    bool shouldSchedule = false;
    lock (_achievementBatchLock)
    {
        // NULL JNI-kostnad på spillsløyfetråden — ren aggregering i minnet!
        if (_pendingIncrements.TryGetValue(achievementId, out int current))
            _pendingIncrements[achievementId] = current + steps;
        else
            _pendingIncrements[achievementId] = steps;

        if (!_incrementFlushScheduled)
        {
            _incrementFlushScheduled = true;
            shouldSchedule = true;
        }
    }

    if (shouldSchedule)
    {
        Task.Run(async () =>
        {
            await Task.Delay(1500).ConfigureAwait(false);
            FlushPendingIncrementsNow();
        });
    }
}

private void FlushPendingIncrementsNow()
{
    List<KeyValuePair<string, int>>? snapshot = null;

    lock (_achievementBatchLock)
    {
        _incrementFlushScheduled = false;
        if (_pendingIncrements.Count == 0) return;

        snapshot = new List<KeyValuePair<string, int>>(_pendingIncrements);
        _pendingIncrements.Clear();
    }

    var act = _activity;
    if (act == null || act.IsFinishing || act.IsDestroyed) return;

    var client = PlayGames.GetAchievementsClient(act);
    foreach (var kvp in snapshot)
    {
        if (kvp.Value > 0)
        {
            // 150 rammehendelser blir til 1 kombinert trinnkall til GPGS
            client.Increment(kvp.Key, kvp.Value);
        }
    }
}

5. Hvordan sporer spillere prestasjonene sine i spillet?

Popup-varsler under kamp er fantastiske, men spillere trenger også et oversiktlig sted for å bla gjennom låste merker, sjekke prosentvis fremgang på trinnvise nivåer og velge sitt neste mål.

For å støtte dette på en elegant måte, forvandlet vi vår mobile statistikkskjerm til et samlet STATS & RANKS-senter. Øverst på skjermen pulserer to gyldne knapper—LEADERBOARD og ACHIEVEMENTS—med en jevn 2-sekunders sinusbølgeglød (Math.Sin). På Windows Desktop-versjoner skjules disse mobilspesifikke knappene automatisk, slik at det klassiske og ryddige oppsettet for STATISTICS bevares.

Når spilleren trykker på ACHIEVEMENTS:

  1. FlushPendingIncrementsNow() kjøres umiddelbart slik at eventuell fremgang fra de siste 1,5 sekundene blir sendt inn før brukergrensesnittet åpnes.
  2. GetAchievementsIntent() åpner det native overlegget for Prestasjoner fra Google Play Games direkte over spillet:

Native Google Play Games Achievements Overlay in Blocked: Pixel Panzer
Det native Google Play Games Achievements-overlegget åpnet fra STATS & RANKS-skjermen, som viser total fullføring (2 / 79), anbefalte mål, ulåste merker (Loyal Supporter, Audiophile) og låste trinnvise ringer.

Spillere kan inspisere sin 2 / 79-fremgang, se personlige anbefalinger og spore trinnvise prosentringer uten noensinne å forlate appen.


6. Konklusjon og våre spill

Når det er bygget med et balansert budsjett på 2 000 XP og en ikke-blokkerende bakgrunnsbatching-pipeline, er Google Play Games Achievements en av de mest effektive måtene å tilføre dybde og langsiktig gjenspillingsverdi til et arkadespill uten å ofre bildefrekvensen.

Hvis du vil oppleve vårt progresjonssystem med 79 prestasjoner, ColorWheel-kampmekanikker og globale ledertavler selv—eller sjekke ut våre andre titler—finner du dem i butikkene nedenfor:

🎮 Våre spill:

📢 Følg våre utviklerlogger og fellesskap:

Følg oss for flere tekniske artikler, bak kulissene-klipp og spilloppdateringer:


Emneknagger og temaer

#GooglePlayGames #Achievements #MonoGame #CSharp #MobileGameDev #AndroidDev #IndieDev #GameArchitecture #BlockedPixelPanzer #PaintTrek #ArarGames




Hiç yorum yok:

Yorum Gönder