Mobil Oyunlarda Google Play Games Nailiyyətlər (Achievements) Sistemi: Mağaza Təsiri, 2.000 XP Limiti və MonoGame Memarlığı
Bir mobil oyunu hazırlayıb mağazada yayımladıqdan sonra əsl sınaq başlayır: oyunçunun ilk bir neçə dəqiqəlik marağını uzunmüddətli bağlılığa çevirmək. Oyunçular sadəcə "mərhələni keç, növbətiyə başla" dövrəsi ilə baş-başa qaldıqda, bir müddət sonra yorğunluq yaranır və ya qurduğunuz dərin oyun mexanikalarının yarısını belə kəşf etmədən tətbiqi bağlayırlar.
İlk baxışda Google Play Games Services (GPGS) Nailiyyətlər (Achievements) sistemi sadəcə kiçik nişanlar toplusu kimi görünə bilər. Lakin düşünülmüş şəkildə dizayn edildikdə, o, oyunçuları oyununuzun mexanikasının hər bir qatına yönləndirən güclü bir saxlama (retention) mühərrikinə çevrilir.
Bu texniki məqalədə nailiyyətlərin Google Play ekosistemində real olaraq nə qazandırdığını, Blocked: Pixel Panzer üçün Google-un sərt XP qaydaları çərçivəsində 79 fərqli nailiyyəti necə dizayn etdiyimizi və gərgin arkada döyüşləri zamanı FPS düşüşlərinin və Android ANR (Application Not Responding) xətalarının qarşısını alan asinxron MonoGame / C# batching mexanizmini necə qurduğumuzu təhlil edirik.
1. Google Play Games Nailiyyətləri Niyə Əhəmiyyətlidir?
Google Play Games nailiyyətlərini inteqrasiya etmək həm oyunçu psixologiyası, həm də mağaza performans göstəriciləri üzrə dörd konkret fayda təmin edir:
- Alternativ Hədəflər və Oyunçu Bağlılığı (Day-7 / Day-30 Retention):
Hər bir oyunçu qlobal liderlər cədvəlində (leaderboard) 1-ci yeri tuta bilməz, lakin hər kəs "100 Qüllə Məhv Et" və ya "Heç bir zərər almadan mərhələni tamamla" hədəfinə doğru irəliləyə bilər. Pilləli (incremental) nailiyyətlər hər oyun sessiyasında irəliləyən real bir tərəqqi paneli təqdim edir. - Oyun Mexanikalarını Təbii Yolla Öyrətmək (Gizli Onboarding):
Oyunçular çox vaxt standart silahlarından istifadə edir və yeni üsulları sınamaqdan çəkinirlər. Blocked: Pixel Panzer-də ColorWheel üzərində yaşıl turşu gülləsi ilə blokları eyni vaxtda əritməyə və ya qara güllə ilə kritik zərbələr endirməyə görə nailiyyət vermək, onları hər bir elementar rejimi kəşf etməyə və mənimsəməyə təşviq edir. - Anlıq Əks-Əlaqə və Google Play Oyunçu XP-si:
Qızğın döyüşün ortasında rəsmi Google Play Games bildirişinin ekranın yuxarısından enməsini görmək və qlobal Google Play Oyunçu Səviyyəsi üçün XP qazanmaq oyunçulara əməliyyat sistemi profili ilə əlaqəli qalıcı bir irəliləyiş hissi verir. - Google Play Ekosistemi və Keyfiyyət Siqnalları:
Google Play Games Services V2 (PGS V2) inteqrasiyası Zero-Tap avtomatik daxilolma, Google Play Games on PC ilə tam uyğunluq və Google Play Store-un "Oyunlar" bölməsində daha güclü cəlbetmə siqnalları qazandırır.
2. Google Play Console Qaydaları: 2.000 XP Limiti və 10.000 Addım Qaydası
Google Play Console-da nailiyyətləri tənzimləyərkən üç sərt platforma məhdudiyyətini nəzərə almalısınız:
- 2.000 XP Sərt Limiti (Hard Cap): Tək bir oyunda bütün nailiyyət xallarının cəmi 2.000 XP-dən çox ola bilməz. Hər bir fərdi nailiyyət 5 ilə 200 XP arasında olmalı və 5-in qatları şəklində verilməlidir.
- Pilləli Nailiyyətlər üçün 10.000 Addım Limiti: Kumulyativ sayğaclı nailiyyətlər Play Console-da maksimum 10.000 addımı (steps) dəstəkləyir.
- Play Games Services V2 Tələbi: Google köhnə V1 SDK-nı ləğv edir. Müasir Android oyunları
Xamarin.GooglePlayServices.Games.V2(PlayGamesSdkvəPlayGames.GetAchievementsClient) üzərində qurulmalıdır.
Blocked: Pixel Panzer-də 79 Nailiyyətlik Kataloq Dizaynı
Əsas oyun obyektlərimizi (TurretBlock, FighterJet, EnemyRocket, ColorWheel, HydraRegenerationSkill, Season) təhlil edərək, 6 əsas kateqoriya üzrə cəmi 1.995 / 2.000 XP dəyərində 79 nailiyyət formalaşdırdıq:
| Kateqoriya | Nümunə Nailiyyətlər | Növ | Hədəf / Mexanika |
|---|---|---|---|
| Düşmən Ovçuları | Jet Hunter I–III, Sky Dominator, Turret Buster I–III, Siege Master |
Pilləli | 10, 100, 1.000 və 10.000 qırıcı təyyarə, müdafiə qülləsi və idarəolunan raket məhv etmək. |
| Blok Dağıdılması və Partlayıcılar | Pioneer Breaker, Demolition Crew, Crusher Supreme, Pixel Obliterator, Chain Reaction |
Pilləli / Standart | 1.000-dən 10.000-ə qədər blok qırmaq və tək dinamit partlayışı ilə 5/25/50 hədəfi partlatmaq. |
| ColorWheel və Silah Ustalığı | Prismatic Pilot, Acid Dissolver, Critical Striker, Power Blaster, Speedy Sprinter, Beam Vaporizer |
Pilləli | Yaşıl turşu gülləsi ilə blokları əritmək, qara kritik vuruşlar etmək, qırmızı güc atışları, lazerlər və idarəolunan raketlər. |
| Mərhələ və Boss İrəliləyişi | First Blood, Giant Slayer, Decimator, Speedrunner I–III |
Pilləli / Standart | İlk düşmən məhvi, ilk Boss qələbəsi və mərhələləri 4 dəqiqədən az müddətdə tamamlamaq. |
| Purist (Bacarıqsız / Xəsarətsiz) Sınaqlar | Untouchable, Clean Victory I–III, Purist Gladiator, Mono Specialist |
Pilləli / Standart | Heç bir zərər almadan və ya heç bir bacarıq (skill) istifadə etmədən Bossları məğlub etmək və yüksək səviyyəli mərhələləri keçmək. |
| Atmosfer, Təchizat və Meta | Storm Fighter, Retro Connoisseur, Gem Tycoon, Quad Spectrum, Audiophile, Loyal Supporter |
Pilləli / Gizli | Yağışlı havada 100 qüllə dağıtmaq, CRT monitorları toplamaq və musiqi pleyerində tam treklərə qulaq asmaq. |
Hər bir nailiyyət üçün çətinlik artdıqca çərçivələri bürüncdən qızıla və prizmatik pillələrə yüksələn xüsusi 512x512 piksel-art nişan ikonları hazırladıq:
Peşəkar Məsləhət (Toplu ZIP İdxalı): 79 nailiyyəti Google Play Console veb interfeysində əllə tək-tək daxil etmək saatlarla vaxt aparır. Əvəzində
AchievementsMetadata.csv,AchievementsIconsMappings.csvvə 512x512.jpgikonlarınızı tək bir.ziparxivində birləşdirərək Play Console-un "Import achievements" funksiyasından istifadə edin və bütün kataloqu saniyələr ərzində idxal edin.
3. Təmiz Arxitektura: Ortaq Kodda IGamesService və AchievementDirector
Blocked: Pixel Panzer həm Windows PC (Microsoft Store), həm də Android (Google Play) üzərində işləyən kross-platformalı MonoGame layihəsidir. Ortaq oyun layihəmizi (Blocked.Shared) Android SDK asılılıqlarından tamamilə azad saxlamaq üçün Asılılığın İnversiyası Prinsipini (Dependency Inversion Principle - SOLID) tətbiq edirik.
Əvvəlcə ortaq təbəqədə platformadan asılı olmayan IGamesService interfeysini təyin edirik:
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();
}
}
Nailiyyət yoxlamalarını CollisionManager, GameplayScreen və Player daxilində səpələmək əvəzinə, bütün 79 qaydanı AchievementDirector adlı vahid əlaqələndirici sinifdə mərkəzləşdiririk:
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; // Safely no-ops on Desktop PC builds
if (isTurret)
{
gamesService.IncrementAchievement(AchievementIds.TurretBuster1, 1);
gamesService.IncrementAchievement(AchievementIds.TurretBuster2, 1);
gamesService.IncrementAchievement(AchievementIds.TurretBuster3, 1);
gamesService.IncrementAchievement(AchievementIds.SiegeMaster, 1);
// Turrets destroyed during rainy weather advance "Storm Fighter"
if (Season.Current == SeasonKind.Rainy)
{
gamesService.IncrementAchievement(AchievementIds.StormFighter, 1);
}
}
TrackWeaponKill(gamesService, killingBullet, killedByLaser);
}
}
4. Kritik Mühəndislik: ANR-lərin Qarşısını Almaq Üçün JNI / Binder IPC Yükünün Aradan Qaldırılması
Sürətli templi arkada oyununda nailiyyət tətikləyicilərini birbaşa Google Play SDK-ya bağlamaq ciddi performans tələsi yaradır:
Oyunçu Partlayıcı Bloku (ExplosiveBlock) partlatdıqda və ya Laser Beam bacarığından istifadə etdikdə, tək bir kadrda (16.6 millisaniyə) 20-30 blok və düşmən məhv edilə bilər. Hər bir məhvetmə 5 və ya 6 pilləli səviyyəni yenilədikdə, tək bir kadr 150-dən çox IncrementAchievement çağırışını işə sala bilər!
Əgər əsas oyun dövrəsi axınında (thread) Google Play Services-ə 150 sinxron JNI və Binder IPC çağırışı göndərsəniz:
- Başlanğıc səviyyəli Android cihazları (1–2 GB RAM-a malik Android Go telefonları) dərhal ciddi kadr donmalarından əziyyət çəkir.
- JNI Qlobal İstinad (GREF) cədvəli şişir və Google Play Vitals-da ANR (
Input dispatching timed out) hesabatlarına səbəb olur.
Bizim Həllimiz: Yaddaşda 1.5 Saniyəlik Qruplaşdırma (Batching) və Sessiya Təkrarlanmasının Qarşısının Alınması
GooglePlayGamesService.cs daxilindəki tətbiqimiz MonoGame yeniləmə dövrəsini Google Play IPC çağırışlarından tamamilə təcrid edir:
- Sessiya Təkrarlanmasının Qarşısının Alınması (
_unlockedInSession):
Standart nailiyyət bir sessiya ərzində açıldıqdan sonra onun ID-siHashSet<string>-ə əlavə edilir. Eyni və ya sonrakı kadrlarda təkrarlanan tətiklənmələr sıfır JNI xərci ilə birbaşa C#-da geri qayıdır. - 1.5 Saniyəlik Arxa Plan Qruplaşdırması (
_pendingIncrements):
IncrementAchievementçağırışı sadəcə əsas axında yaddaşdakıDictionary<string, int>daxilində tam ədədi artırır (sıfır JNI çağırışı). Arxa planTask.Runişçisi 1.5 saniyədən sonra oyanır, toplanmış cəmlərin anlıq görüntüsünü (snapshot) alır və onları Google Play Services-ə hər nailiyyət üçün vahid birləşdirilmiş çağırışla göndərir. 26502: CLIENT_RECONNECT_REQUIREDİdarə Edilməsi və Oflayn Keşləmə:
Oyunçu oyunu saatlarla arxa plana atıb geri qayıtdıqda, Google Play sessiya tokeninin vaxtı bitə bilər və26502 (CLIENT_RECONNECT_REQUIRED)xətası verə bilər. Xidmətimiz bunu tutur, cooldown mühafizəsi ilə tək bir səssiz arxa planSignIn()cəhdi edir və cihaz oflayndırsa, GPGS-in lokal oflayn keşinə (client.Unlock) müraciət edir—bu da oyunçunun heç bir nailiyyətinin itirilməməsini təmin edir.
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)
{
// ZERO JNI cost on the game loop thread — pure in-memory aggregation!
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 frame events become 1 combined step call to GPGS
client.Increment(kvp.Key, kvp.Value);
}
}
}
5. Oyunçular Öz Nailiyyətlərini Oyun Daxilində Necə İzləyirlər?
Döyüş zamanı açılan bildirişlər əladır, lakin oyunçuların kilidli nişanlara baxmaq, pilləli səviyyələrdə faiz tərəqqisini yoxlamaq və növbəti hədəflərini seçmək üçün aydın bir məkana da ehtiyacı var.
Bunu səliqəli şəkildə dəstəkləmək üçün mobil statistika ekranımızı vahid STATS & RANKS mərkəzinə çevirdik. Ekranın yuxarısında iki qızılı düymə—LEADERBOARD və ACHIEVEMENTS—2 saniyəlik hamar sinus dalğası parıltısı ilə (Math.Sin) döyünür. Windows Desktop versiyalarında bu mobil düymələr avtomatik olaraq gizlənir və klassik STATISTICS tərtibatının təmizliyini qoruyur.
Oyunçu ACHIEVEMENTS düyməsinə toxunduqda:
- İnterfeys açılmazdan əvvəl son 1.5 saniyəlik hər hansı tərəqqinin qeydə alınması üçün
FlushPendingIncrementsNow()dərhal icra edilir. GetAchievementsIntent()birbaşa oyunun üzərində Google Play Games-in yerli Achievements pəncərəsini açır:
Oyunçular tətbiqdən çıxmadan öz 2 / 79 tərəqqisini yoxlaya, fərdiləşdirilmiş tövsiyələrə baxa və pilləli faiz halqalarını izləyə bilərlər.
6. Nəticə və Oyunlarımız
Balanslaşdırılmış 2.000 XP büdcəsi və bloklamayan arxa plan batching boru kəməri ilə qurulduqda, Google Play Games Nailiyyətləri kadr sürətini qurban vermədən arkada oyununa dərinlik və uzunmüddətli təkrar oynanıla bilənlik əlavə etməyin ən təsirli yollarından biridir.
Əgər 79 nailiyyətlik irəliləyiş sistemimizi, ColorWheel döyüş mexanikasını və qlobal liderlər cədvəlini şəxsən təcrübədən keçirmək və ya digər oyunlarımızla tanış olmaq istəyirsinizsə, onları aşağıdakı mağazalarda tapa bilərsiniz:
🎮 Oyunlarımız:
- 🛡️ Blocked: Pixel Panzer:
ColorWheel elementar sursatları, dinamik hava şəraiti, Boss döyüşləri, qlobal liderlər cədvəli və 79 Google Play nailiyyəti olan retro piksel tank döyüşü!
👉 Google Play-də yükləyin (Android & PC) | Microsoft Store (Windows PC) - 🎨 Paint Trek:
Refleksləri və taktiki hərəkəti birləşdirən sürətli və rəngarəng kosmik arkada atıcısı.
👉 Google Play | Microsoft Store (PC & Xbox) - 🚀 Space Dodger:
Dərin kosmosda yüksək sürətli retro arkada maneələrdən yayınma oyunu.
👉 Google Play-də yükləyin
📢 Devloqlarımızı və İcmamızı İzləyin:
Daha çox texniki məqalə, pərdəarxası görüntülər və oyun yeniləmələri üçün bizi izləyin:
- 🎵 TikTok: @arargamesstudio
- 📸 Instagram: @arargamesstudio
- 🐦 X (Twitter): @arargamesstudio
- 📺 YouTube: @koreaaria
- 🧵 Threads: @arargamesstudio
- 📘 Facebook: arargamesstudio
Tags & Topics
#GooglePlayGames #Achievements #MonoGame #CSharp #MobileGameDev #AndroidDev #IndieDev #GameArchitecture #BlockedPixelPanzer #PaintTrek #ArarGames
Hiç yorum yok:
Yorum Gönder