Godot 4.5 ile AdMob Reklam Entegrasyonu: Kesin ve Çalışan Rehber
Godot motorunda oyun geliştiriyorsanız ve oyununuzdan gelir elde etmek istiyorsanız, AdMob entegrasyonu en popüler ve etkili yöntemlerden biridir. Ancak, doğru eklentiyi seçmek, yapılandırmak ve özellikle "Ödüllü Reklamlar" (Rewarded Ads) gibi karmaşık sistemleri sorunsuz çalıştırmak zorlayıcı olabilir.
Bu makalede, Godot 4.5 versiyonu ve güncel AdMob eklentilerini kullanarak sıfır hatalı, stabil bir reklam entegrasyonunun nasıl yapılacağını adım adım inceleyeceğiz. Sık karşılaşılan hatalara ve çözüm yollarına da değineceğiz.
1. Hazırlık ve Eklenti Kurulumu
Godot 4.x için resmi ve en stabil AdMob eklentisi genellikle Poing Studios (veya benzeri güvenilir geliştiriciler) tarafından sağlanan eklentilerdir.
Eklenti Kurulum Adımları:
- İlgili AdMob eklentisini indirin ve projenizin addons/ klasörüne dahil edin.
- Godot'un Project -> Project Settings -> Plugins sekmesinden eklentiyi aktifleştirin.
- Eklenti aktifleştirildiğinde, genellikle alt panelde veya proje ayarlarında bir "AdMob" bölümü oluşur. Yada Proje menüsüne eklenir; Proje -> Araçlar -> AdMob Manager
En Önemli Adım (AdMob App ID): AdMob panelinden (veya test için Google'ın sağladığı) App ID'nizi almanız gerekir. Bu ID genellikle ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY formatındadır. Bu ID'yi eklentinin ayarlarına veya Android export ayarlarındaki ilgili meta-data bölümüne (AndroidManifest.xml içine gömülecek şekilde) mutlaka girmelisiniz. Godot 4.5 ve Poing.Studios’a ait AdMob eklentisi için App ID’nin girileceği dosya Addons -> AdMob -> Android -> setup.gd dosyasıdır.
2. Doğru Kod Mimarisi (Güvenli Yükleme ve Gösterme)
Reklamları yönetirken, oyununuzun çökmesini önlemek için "Güvenli Yükleme" ve "Callback (Geri Çağırma)" mantığını doğru kurmak çok önemlidir.
İşte Game Manager betiğinizde kullanmanız gereken kesin yapı:
A. Değişkenleri Tanımlama
Test aşamasında mutlaka Google'ın sağladığı test ID'lerini kullanın. Gerçek ID'ler ile test yaparsanız AdMob hesabınız banlanabilir!
# --- ADMOB TEST ID'LERİ ---
const BANNER_ID = "ca-app-pub-3940256099942544/6300978111"
const INTERSTITIAL_ID = "ca-app-pub-3940256099942544/1033173712"
const REWARDED_ID = "ca-app-pub-3940256099942544/5224354917"
# --- REKLAM DEĞİŞKENLERİ ---
var _ad_view = null
var _interstitial_ad = null
var _rewarded_ad = null
var _reward_earned: bool = false
var _waiting_for_reward: bool = false
var _inter_loader = null
var _inter_cb = null
var _fs_inter_cb = null
var _rew_loader = null
var _rew_cb = null
var _fs_rew_cb = null
var _current_rew_listener = null
B. AdMob'u Başlatma (Initialization)
AdMob SDK'sını oyun başlarken bir kez başlatmanız gerekir. Bu işlem genellikle işletim sistemi kontrolü ile yapılır (Sadece Android/iOS'te çalışması için).
func _setup_admob() -> void:
# Windows/macOS/Linux'ta reklam yüklemeye çalışma, çökmeyi önle
if OS.get_name() in ["Windows", "macOS", "Linux"]: return
var mobile_ads: Variant = MobileAds
if mobile_ads and mobile_ads.has_method("initialize"):
if not Engine.has_meta("admob_initialized"):
mobile_ads.initialize()
Engine.set_meta("admob_initialized", true)
# Banner reklamı hemen yükle ve göster
await get_tree().create_timer(0.2).timeout
var req_class: Variant = AdRequest
if not req_class: return
var ad_request = req_class.new()
var ad_view_class: Variant = AdView
var ad_size_class: Variant = AdSize
var ad_pos_class: Variant = AdPosition
if ad_view_class:
_ad_view = ad_view_class.new(BANNER_ID, ad_size_class.BANNER, ad_pos_class.Values.BOTTOM)
if _ad_view:
_ad_view.load_ad(ad_request)
_ad_view.show()
C. Ödüllü Reklam (Rewarded Ad) Yükleme ve Gösterme Mantığı
Ödüllü reklamlar en karmaşık olanlardır çünkü kullanıcının reklamı sonuna kadar izleyip izlemediğini (Ödül kazanıp kazanmadığını) güvenli bir şekilde takip etmeniz gerekir.
func _load_and_show_rewarded(btn_ad: Button, reason: String) -> void:
btn_ad.text = "Reklam Yükleniyor..."
btn_ad.disabled = true
# PC'de test ediyorsan direkt ödülü ver
if OS.get_name() in ["Windows", "macOS", "Linux"]:
_give_reward_safely()
return
var rew_loader_class: Variant = RewardedAdLoader
var rew_cb_class: Variant = RewardedAdLoadCallback
if rew_loader_class and rew_cb_class:
_rew_loader = rew_loader_class.new()
_rew_cb = rew_cb_class.new()
var w_self = weakref(self)
var on_r_loaded = func(ad):
var s = w_self.get_ref()
if s:
s._rewarded_ad = ad
if is_instance_valid(btn_ad): btn_ad.text = "Reklam Gösteriliyor..."
# Kapatılma (Dismiss) Callback'i
var fs_class: Variant = FullScreenContentCallback
if fs_class:
s._fs_rew_cb = fs_class.new()
var w_s2 = weakref(s)
var on_dismiss = func():
var s2 = w_s2.get_ref()
if s2:
# Reklam kapandığında, eğer ödül kazanılmışsa ödülü ver
if s2._reward_earned or s2._waiting_for_reward:
s2._give_reward_safely()
else:
# Kullanıcı reklamı yarıda kapattı
if is_instance_valid(btn_ad):
btn_ad.text = "🎥 REKLAM İZLE"
btn_ad.disabled = false
if s._fs_rew_cb.has_method("set_on_ad_dismissed_full_screen_content"):
s._fs_rew_cb.set_on_ad_dismissed_full_screen_content(on_dismiss)
else:
s._fs_rew_cb.on_ad_dismissed_full_screen_content = on_dismiss
ad.full_screen_content_callback = s._fs_rew_cb
# Ödül Kazanılma (Earned Reward) Callback'i
var listener_class: Variant = OnUserEarnedRewardListener
if listener_class:
s._current_rew_listener = listener_class.new()
var on_earned = func(item):
var s3 = w_self.get_ref()
if s3: s3._reward_earned = true # Sadece bayrağı işaretle
if s._current_rew_listener.has_method("set_on_user_earned_reward"):
s._current_rew_listener.set_on_user_earned_reward(on_earned)
else:
s._current_rew_listener.on_user_earned_reward = on_earned
ad.show(s._current_rew_listener)
else:
ad.show()
else:
if ad and ad.has_method("destroy"): ad.destroy()
var on_r_failed = func(err):
var s = w_self.get_ref()
if s and is_instance_valid(btn_ad):
btn_ad.text = "Yüklenemedi! Tekrar Dene"
btn_ad.disabled = false
# Callback'leri bağla ve yüklemeyi başlat
if _rew_cb.has_method("set_on_ad_loaded"):
_rew_cb.set_on_ad_loaded(on_r_loaded)
_rew_cb.set_on_ad_failed_to_load(on_r_failed)
else:
_rew_cb.on_ad_loaded = on_r_loaded
_rew_cb.on_ad_failed_to_load = on_r_failed
var req_class: Variant = AdRequest
if req_class: _rew_loader.load(REWARDED_ID, req_class.new(), _rew_cb)
D. Ödülü Güvenlice Verme
Ödül verme işlemini doğrudan on_user_earned_reward içinde yapmak bazen Godot'un thread (iş parçacığı) sisteminde çökmelere neden olabilir. Bu yüzden o fonksiyon sadece _reward_earned = true yapar, ödülü ise reklam kapandıktan sonra tetiklenen on_ad_dismissed içinden çağırdığımız _give_reward_safely() fonksiyonunda veririz.
func _give_reward_safely() -> void:
_reward_earned = false
_waiting_for_reward = false
# Ödülü ver (Örn: +10 Elmas)
_saved_diamonds += 10
save_progress()
show_info_popup("TEBRİKLER!", "+10 Elmas kazandınız! 💎")
update_ui()
E. Hafıza Yönetimi (Memory Leaks Önleme)
Sahne değişirken veya oyun kapanırken reklam objelerini hafızadan temizlemek çok önemlidir, aksi takdirde uygulamanız zamanla yavaşlayabilir veya çökebilir.
func _exit_tree() -> void:
if _ad_view != null:
if _ad_view.has_method("destroy"): _ad_view.destroy()
_ad_view = null
if _interstitial_ad != null:
if _interstitial_ad.has_method("destroy"): _interstitial_ad.destroy()
_interstitial_ad = null
if _rewarded_ad != null:
if _rewarded_ad.has_method("destroy"): _rewarded_ad.destroy()
_rewarded_ad = null
_inter_loader = null
_inter_cb = null
_fs_inter_cb = null
_rew_loader = null
_rew_cb = null
_fs_rew_cb = null
_current_rew_listener = null
3. Karşılaşılan Tuzaklar ve Çözümler
Tuzak 1: Hatalı Class Referansları Yüzünden Çökme
Belirti: Reklam butonuna basıldığında oyun donuyor veya kapanıyor. Neden: Eklentinin sağladığı sınıfları (Örn: RewardedAdLoader) doğrudan RewardedAdLoader.new() olarak çağırıyorsunuz. Eğer eklenti doğru yüklenmediyse, Godot bu sınıfı bulamaz ve çöker. Çözüm: Yukarıdaki mimaride kullandığımız gibi, sınıfları önce Variant olarak kontrol edip (var rew_loader_class: Variant = RewardedAdLoader), var olup olmadıklarını teyit ettikten sonra kullanın. Bu sayede eklenti yoksa bile oyun çökmez, sadece reklam çalışmaz.
Tuzak 2: PC'de Test Ederken Oyunun Çökmesi
Belirti: Godot editöründen oyunu başlattığınızda siyah ekran geliyor veya hata veriyor. Neden: AdMob sadece Android ve iOS ortamlarında çalışır. PC'de Java köprüsü olmadığı için SDK başlatılamaz. Çözüm: AdMob fonksiyonlarının en başına daima OS kontrolü ekleyin: if OS.get_name() in ["Windows", "macOS", "Linux"]: return
Tuzak 3: Zayıf Referans (Weakref) Kullanılmaması
Belirti: Reklam izlenirken sahne değiştirildiğinde veya obje silindiğinde Null Instance hatası alınıyor. Neden: Callback fonksiyonları (Lambda fonksiyonları) içinde doğrudan self (yani bulunduğunuz sahne) kullanırsanız, reklam izlenirken o sahne silinirse kod silinmiş bir objeye ulaşmaya çalışır. Çözüm: Mimarimizde gösterildiği gibi, weakref(self) kullanarak sahnenin hala var olup olmadığını kontrol edin (var s = w_self.get_ref(); if s:).
Tuzak 4: Gerçek Reklam ID'leri ile Test Yapmak
Belirti: Birkaç gün sonra AdMob hesabınız sınırlandırılır veya kapatılır. Neden: Geliştirme aşamasında kendi uygulamanızdaki gerçek reklamlara tıklamanız, AdMob'un geçersiz trafik politikalarını ihlal eder. Çözüm: Uygulamanız Google Play Store'a yüklenip onaylanana kadar DAİMA Google'ın sağladığı genel test reklam ID'lerini kullanın.
Son Söz
AdMob entegrasyonu, asenkron işlemler (callback'ler) ve platforma özgü sınırlamalar nedeniyle dikkat gerektirir. Yukarıdaki mimari, olası çökmeleri önlemek için "defansif programlama" (defensive programming) teknikleriyle hazırlanmıştır ve Godot 4.x projelerinde güvenle kullanılabilir.
Yorumlar
Yorum Yaz