Unity 3D Android Oyunlarınıza AdMob Reklamları Eklemek – Resimli Anlatım

Yayınlandı: 26 Mayıs 2014 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

ÖNEMLİ: Artık bu dersi güncellemeyi planlamıyorum ve dersi yeni yorumlara kapatarak da AdMob desteğimi tamamen sonlandırdım. Aldığım yorumların çoğu reklamların niçin gözükmediği hakkında ve artık ben sıkıntının benim kodumda mı yoksa AdMob’da mı olduğunu anlamıyorum. Ne siz vaktinizi bu ders ile boşa harcayın ne de ben vaktimi reklamların niçin gözükmediğini tahmin etmek ile boşa harcayayım (bana bu tarz soru soranlar lütfen kişisel algılamasın). Benim önerim, AdMob entegrasyonu için AdMob’un kendi dokümantasyonundan faydalanmanız yönünde. İsterseniz alternatif olarak Unity Ads reklamlarına da göz atabilirsiniz.

GÜNCELLEME – 21.01.2024: Ders AdMob’un en güncel sürümüne uygun şekilde güncellendi.

Hepinize merhaba,

Bana gerek Facebook’tan gerek başka platformlardan, Unity‘de yapılan Android oyunlarına nasıl reklam eklenebileceği ile ilgili çok fazla soru geliyordu. Ama kendi oyunlarıma hiç reklam eklemediğimden ben de bilmiyordum. Hem kendim bu işin nasıl yapıldığını öğrenmek hem de size göstermek için bu yazıyı yazıyorum.

Derste AdMob reklamlarını kullanacağız (dersin devamında Unity Ads için mediation talimatları da mevcut). Eğer henüz Android SDK‘yı kurmadıysanız, sizi önce şuraya alayım: https://yasirkula.com/2013/07/17/unity-android-sdk-kurulumu-resimli-anlatim/

Yazıyı yazarken faydalandığım kaynak: https://developers.google.com/admob/unity/start

İlk yapmanız gereken, şu adresten GoogleMobileAds.unitypackage‘ı indirmek: https://github.com/googleads/googleads-mobile-plugins/releases/latest

Sonrasında AdMob web sitesinden yeni bir hesap oluşturun (Gmail hesabı gerekli) veya mevcut hesabınızla sisteme giriş yapın: https://admob.google.com/home/

Hesabınızı oluşturduktan ve sisteme giriş yaptıktan sonra, solda yer alan menüden Uygulamalar-UYGULAMA EKLE yolunu izleyip hesabınıza yeni bir uygulama ekleyin. Yeni oluşturduğunuz uygulamaya reklam eklemek için, sol menüden Uygulamalar-Uygulama_İsmi‘ni seçin ve yine sol menüde yer alan Reklam birimleri‘ne tıklayın. Son olarak da, gelen ekrandan Reklam birimi ekleyin butonuna tıklayın.

a) Banner Reklamlar

Reklam türü olarak Banner seçin ve bir Reklam birimi adı girin (mesela İlk Banner Reklamım). Reklam birimi oluşturun butonuna tıklayarak işlemi sonlandırın.

b) Interstitial (Geçiş)(Tam ekran) Reklamlar

Yine banner reklamda olduğu gibi, özgün bir Reklam birimi adı girip reklam biriminizi oluşturun.

c) Rewarded (Ödüllü) Video Reklamlar

Bu video reklam türünde, kullanıcı reklamı baştan sona izlediği taktirde kullanıcıyı oyun içerisinde bir şekilde ödüllendirmeniz gerekir (örneğin 100 altın vererek). Bu durumda Ödül ayarları‘ndan Ödül miktarı olarak 100, Ödül öğesi olarak da altın girebilirsiniz. Burada belirlediğiniz değerler Unity kodunuza parametre olarak gittiği için, burası vasıtasıyla kullanıcıların reklam izleyerek kazandığı altın sayısını dinamik olarak değiştirebilirsiniz (Unity kodunuzu değiştirmeye gerek kalmadan). Tabi dilerseniz bu değerleri yok sayabilir ve reklam izlenince kaç altın kazanılacağını direkt Unity kodunuzda belirleyebilirsiniz.

Reklam birim(ler)inizi oluşturduktan sonra Tamamlandı butonuna tıklayarak işlemi sonlandırın. Reklam birimleri menüsünden yeni oluşturduğunuz reklama tıklayın ve gelen ekranda sağ üstten Uygulama talimatları‘na basın. Burada gözüken uygulama kimliğinizi ve reklam birimi kimliğinizi bir yere not edin (ca-app-pub- kısmını da ilave etmeyi unutmayın!):

DİKKAT: bu kimliklerinizi internette kimseyle paylaşmayın. Kimlikleriniz kötü niyetli birinin eline geçerse, bu kişi AdMob hesabınızı banlatabilir. Eğer reklam kodunuzu internette paylaşacaksanız, kimliklerinizi koddan silmeyi unutmayın.

Elle Android SDK kurduysanız, Android SDK‘yı açın ve Extras kısmından “Google Play services“ı kurun. Eğer zaten kuruluysa güncel olduğundan emin olun:

resim6

NOT: işinizi garantiye almak için, Google Play services’a ilaveten en son çıkan iki Android API’sini de yüklemenizi öneririm; örneğin Android 11 (API 30) ve Android 10 (API 29).

Android SDK’yı güncellemeyi bitirdikten sonra şu adımları izleyin:

  • Unity projenizi açıp Build Settings‘ten Platform olarak Android‘i seçin
  • Player Settings-Other Settings‘teki Minimum API Level‘ın “Android 4.1 ‘Jelly Bean’ (API level 16)” veya yukarısı olduğundan emin olun
  • Assets-Import Package-Custom Package… yolunu izleyin ve daha önce indirdiğiniz GoogleMobileAds.unitypackage‘ı projenize import edin (import penceresinde tüm dosyalar seçili olmalı)
  • Edit-Project Settings-Player-Publishing Settings-Build sayfasındaki “Custom Main Gradle Template” ve “Custom Gradle Properties Template” seçeneklerinin açık olduğundan emin olun (Android için)
  • Project panelinde herhangi bir yere sağ tıklayın ve Play Services Resolver-Android Resolver-Resolve yolunu izleyin. İşlem bitene kadar bekleyin
  • Assets-Google Mobile Ads-Settings… yolunu izleyin. Inspector panelinde bir takım ayarlar gözükecek. Google Mobile Ads App ID‘nin altındaki boşluğa uygulama kimliğinizi girin (kimliğin başında veya sonunda boşluk karakteri olmasın! Kodlarınızda reklam kimliklerinizi kullanırken de başta veya sonda boşluk olmadığından emin olun):

En nihayetinde gelelim reklamları uygulamamızda göstermeye…

a) Banner Reklamlar

Diyelim ki oyunun ilk sahnesinde, ekranın tepesinde bir banner reklam göstermek istiyorsunuz. O zaman ReklamBanner adında yeni bir C# scripti oluşturun ve bu script’i sürükleyerek sahnenizdeki bir objeye component olarak verin:

using UnityEngine;
using GoogleMobileAds.Api;
 
public class ReklamBanner : MonoBehaviour
{
	private BannerView reklamObjesi;
 
	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		reklamObjesi = new BannerView( "ca-app-pub-3940256099942544/6300978111", AdSize.Banner, AdPosition.Top );
		AdRequest reklamIstegi = new AdRequest();
		reklamObjesi.LoadAd( reklamIstegi );
	}
 
	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

Kodda ilk olarak MobileAds.Initialize fonksiyonu ile, AdMob plugin’ini kullanıma hazır hale getiriyoruz. Bu fonksiyonu sadece bir kere çağırmanız yeterli. Bu fonksiyon parametre olarak bir callback fonksiyon alıyor ve AdMob kullanıma hazır hale gelince bu callback fonksiyon (AdMobHazirlandi) çağrılıyor. Biz de tüm reklam işlerimizi bu aşamadan sonra gerçekleştiriyoruz.

Plugin’i initialize ettikten sonra, new BannerView() ile yeni bir banner reklam oluşturuyoruz ve bunu reklamObjesi değişkenine değer olarak veriyoruz. Bu fonksiyon 3 parametre alıyor:

  1. Banner reklam kimliğimiz: benim kodda girdiğim kimlik, Admob’un kendi sağladığı ve test reklamları almaya yarayan reklam kimliği. Henüz buraya kendi reklam kimliğinizi girmeyin, öncesinde cihazınızı test cihazı olarak tanıtmanız lazım ki kendi reklam kimliğinizle aldığınız reklamlar test reklamları olsun ve hesabınız yanlışlıkla banlanmasın (test cihazı eklemeyi birazdan göreceğiz). Ayrıca Admob’un sağladığı test reklam kimliğini kullanarak bir nevi kodumuzu da test ediyoruz, eğer kodu doğru yazdıysak oyunu başlatınca banner reklam göreceğiz: yeni oluşturulan reklam kimliklerine birkaç saat boyunca reklam gelmemesi sorunu, Admob’un test reklam kimlikleri için geçerli değil
  2. Banner reklamın ebatları: burada çeşitli seçeneklerimiz mevcut. Eskiden SmartBanner kullanıyordum çünkü bu değer, telefonun ekran boyutuna ve o anki oryantasyonuna (Portrait, Landscape…) bağlı olarak en uygun reklam boyutunu otomatik olarak ayarlıyor. Ancak AdMob SmartBanner’ı deprecate etti ve gelecekte SmartBanner desteği tamamen kalkabilir. O yüzden, AdMob’un kendi örnek kodunda kullandığı Banner türünü seçtim. Eğer başka bir reklam boyutu belirlemek isterseniz, reklam boyutunun ekranın dpi cinsinden boyutundan büyük olmadığından emin olun; aksi taktirde banner reklamlarınız gözükmeyecektir
  3. Banner reklamın ekrandaki konumu: biz reklamın ekranın tepesinde gözükmesi için AdPosition.Top diyoruz ancak mesela ekranın altında gözükmesini istersek AdPosition.Bottom diyebiliriz

Reklam objesini oluşturduktan sonra, bu objeye Admob sunucularından reklam yüklemek için yeni bir AdRequest objesi oluşturuyoruz ve bu objeyi LoadAd fonksiyonu ile reklam objesine veriyoruz.

Son olarak da, OnDestroy içerisinde banner reklamımızı Destroy fonksiyonu ile yok ediyoruz. Reklam script’ini component olarak verdiğiniz obje yok olursa, otomatik olarak Reklam script’inin OnDestroy fonksiyonu çağrılır. Bu örnekte banner reklama erişim sağlayabilen tek script Reklam script’i olduğu için, eğer script yok olduğunda beraberinde banner reklamı da yok etmezsek, memory leak dediğimiz bir sıkıntı olur (hafızadaki banner reklam otomatik olarak yok olmaz ve hafızada yer kaplamaya devam eder) ve bunun tekrarlanması durumunda oyun çökebilir.

b) Interstitial Reklamlar

ReklamInterstitial adında yeni bir C# scripti oluşturun ve bunu sahnenizdeki bir objeye component olarak verin. Yapacağımız şey şu: ekranda bir buton olacak ve biz bu butona tıklayınca Interstitial reklam ekranda belirecek. Bunun için C# scriptinin içeriğini şöyle değiştirin:

using UnityEngine;
using System.Collections;
using GoogleMobileAds.Api;
 
public class ReklamInterstitial : MonoBehaviour
{
	private bool adMobHazir;
	private InterstitialAd reklamObjesi;
 
	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		adMobHazir = true;
	}
 
	// Ekranda test amaçlı "Reklamı Göster" butonu göstermeye yarar, bu fonksiyonu silerseniz buton yok olur
	void OnGUI()
	{
		if( adMobHazir && GUI.Button( new Rect( Screen.width / 2 - 150, Screen.height - 300, 300, 300 ), "Reklamı Göster" ) )
		{
			if( reklamObjesi != null )
			{
				reklamObjesi.Destroy();
				reklamObjesi = null;
			}
			
			AdRequest reklamIstegi = new AdRequest();
			InterstitialAd.Load( "ca-app-pub-3940256099942544/1033173712", reklamIstegi, ( InterstitialAd _reklamObjesi, LoadAdError hata ) =>
			{
				// Eğer reklam yüklenemezse bir hata mesajı log'la
				if( hata != null || _reklamObjesi == null )
				{
					Debug.LogError( "Interstitial reklam yüklenemedi: " + hata );
					return;
				}

				reklamObjesi = _reklamObjesi;
				StartCoroutine( ReklamiGoster() );
			} );
		}
	}
 
	IEnumerator ReklamiGoster()
	{
		while( reklamObjesi == null || !reklamObjesi.CanShowAd() )
			yield return null;

		reklamObjesi.Show();
	}
 
	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

OnGUI fonksiyonu vasıtasıyla ekranda gösterdiğimiz butona bastıktan sonra InterstitialAd.Load ile yeni bir interstitial reklam oluşturuyoruz (daha önceden bir interstitial reklam oluşturdu idiysek onu Destroy fonksiyonu ile yok ediyoruz). Load fonksiyonunun içine bir callback fonksiyon giriyoruz. Reklam yüklendiğinde bu callback fonksiyon otomatik olarak çağrılır. Eğer reklam bir sebepten ötürü yüklenemezse, neden yüklenemediği bilgisi LoadAdError parametresinde tutulur. Reklam sorunsuz olarak yüklenirse, ReklamiGoster() coroutine’i vasıtasıyla reklamın gösterime hazır hale gelmesini bekliyoruz. Reklamın henüz gösterilip gösterilemeyeceğini öğrenmek için InterstitialAd objesinin CanShowAd() fonksiyonunu kullanıyoruz. Reklam gösterime hazırsa da Show() fonksiyonu vasıtasıyla reklamı ekranda gösteriyoruz.

Burada dikkat edilmesi gereken bir nokta, InterstitialAd objesinin Destroy fonksiyonu. Aynı fonksiyon BannerView için de mevcut. Bir reklamla işiniz bittiğinde, o reklam objesinden kurtulmadan önce Destroy fonksiyonu vasıtasıyla reklamın hafızada kapladığı yeri boşaltmalısınız. Aksi taktirde memory leak dediğimiz istenmeyen bir durumla karşı karşıya kalırsınız. Destroy fonksiyonu sadece banner ve interstitial reklamlar için geçerli; yani rewarded reklamlarda böyle bir durum yok.

Banner kodunda olduğu gibi, burada da Admob’un kendi sağladığı interstitial reklam kimliğini kullandım. Cihazımızı test cihazı olarak ekledikten sonra kendi reklam kimliklerimizi test etmeye hazır olacağız (birazdan göreceğiz).

c) Rewarded Video Reklamlar

ReklamRewardedVideo adında yeni bir C# scripti oluşturun ve bunu sahnenizdeki bir objeye component olarak verin. Bu script ile ekranda bir buton oluşturacak ve bu butona tıklayınca rewarded video reklam oynatacağız:

using UnityEngine;
using System.Collections;
using GoogleMobileAds.Api;

public class ReklamRewardedVideo : MonoBehaviour
{
	private bool adMobHazir;
	private RewardedAd reklamObjesi;

	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		adMobHazir = true;
	}

	// Ekranda test amaçlı "Reklamı Göster" butonu göstermeye yarar, bu fonksiyonu silerseniz buton yok olur
	void OnGUI()
	{
		if( adMobHazir && GUI.Button( new Rect( Screen.width / 2 - 150, Screen.height - 300, 300, 300 ), "Reklamı Göster" ) )
		{
			if( reklamObjesi != null )
			{
				reklamObjesi.Destroy();
				reklamObjesi = null;
			}

			AdRequest reklamIstegi = new AdRequest();
			RewardedAd.Load( "ca-app-pub-3940256099942544/5224354917", reklamIstegi, ( RewardedAd _reklamObjesi, LoadAdError hata ) =>
			{
				// Eğer reklam yüklenemezse bir hata mesajı log'la
				if( hata != null || _reklamObjesi == null )
				{
					Debug.LogError( "Rewarded reklam yüklenemedi: " + hata );
					return;
				}

				reklamObjesi = _reklamObjesi;
				StartCoroutine( ReklamiGoster() );
			} );
		}
	}

	IEnumerator ReklamiGoster()
	{
		while( reklamObjesi == null || !reklamObjesi.CanShowAd() )
			yield return null;

		reklamObjesi.Show();
	}
	
	void OyuncuyuOdullendir( Reward odul )
	{
	}

	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

Bu kod interstitial reklam koduna fazlasıyla benziyor. Burada sadece InterstitialAd yerine RewardedAd kullanıyoruz. Sadece reklamı gösterirken Show fonksiyonuna parametre olarak bir callback fonksiyon veriyoruz (birazdan göreceğiz).

Diğer reklam türlerinde olduğu gibi, bu script’te de Admob’un kendi sağladığı test reklam kimliğini kullandım. Cihazımızı test cihazı olarak tanımladıktan sonra kendi reklam kimliklerimizi test etmeye hazır olacağız (birazdan göreceğiz).

Artık oyunu Build alıp cihazda test edebiliriz. Interstitial ve rewarded video reklamların gelmesi biraz sürebilir; hatta sunucuda yeterince reklam yoksa rewarded video reklam hiç gelmeyebilir de (fillrate sorunu).

Build Alma Sorunları

Oyunu build alırken sıkıntı yaşarsanız şu yöntemleri deneyebilirsiniz:

  • Bilgisayarım’a sağ tıklayıp ÖzelliklerGelişmiş sistem ayarlarıOrtam Değişkenleri… yolunu izleyin. Eğer ne Kullanıcı Değişkenleri‘nde ne de Sistem Değişkenleri‘nde JAVA_HOME girdisi yoksa, herhangi bir Yeni… butonuna tıklayıp değerleri şöyle doldurun:
resim8

Eğer sizde “C:\Program Files\Java\jdk1.7.0_51” klasörü yoksa, kendi jdk klasörünüzü bulup Değişken değeri‘ne değer olarak onu yazın. Sonrasında Path isimli sistem değişkenini listeden bulup çift tıklayın ve Değişken değeri‘nin sonuna şunu ekleyin: “;C:\Program Files\Java\jdk1.7.0_51\bin” (eğer değişkenin değeri yukarıdan aşağıya liste olarak gözüküyorsa, baştaki ; işaretine gerek yok). Son olarak bilgisayarınızı yeniden başlatın.

  • SDK Manager‘da “Android SDK Build-tools“un son sürümü kurulu değilse kurun
  • JDK’nın 64-bit’lik sürümünü yüklediyseniz bir de 32-bit’lik sürümünü yüklemeyi deneyin
  • Belki saçma gelecek ancak bazen Admob ile alakalı hatalar, plugin ile gelen tüm dosyaları silip plugini yeniden import ederek çözülüyor (başıma geldi)

Reklam Gözükmemesi Sorunları

Her şeyi düzgün yaptığınıza inanmanıza ve hata almadan build alabilmenize rağmen bir türlü reklam göremiyor musunuz?

  • Eğer uygulama açılır açılmaz kendisini kapatıyorsa, yazının başlarında gösterdiğim GoogleMobileAdsSettings‘e uygulama kimliğinizi doğru girdiğinizden emin olun
  • Cihazınızın internete bağlı olduğundan emin olun
  • (Kendi reklam kimliğiniz ile test ediyorsanız) Eğer reklamı Admob üzerinden daha yeni oluşturduysanız, ertesi gün tekrar deneyin veya başka bir reklam kimliği kullanmayı deneyin. Henüz yeni oluşturulan reklam birimlerine reklam sağlan(a)madığını okumuştum
  • Eğer Gradle build system’ı kullanıyorsanız, Player Settings-Publishing Settings‘te yer alan Minify‘ı hem Release hem de Debug için None yapın
  • Bundle Identifier‘ı rastgele bir şekilde değiştirmeyi deneyin. Bunun sebebi; eğer başka birisi girdiğiniz o Bundle Identifier ile Admob reklamları sunarken ban yemiş ise, artık o Bundle Identifier’ı kullanan uygulamalarda Admob reklamları gözükmeyecektir
  • Play Services Resolver-Android Resolver-Force Resolve yapmayı deneyin
  • Reklam yükleme kodunuzu ilk çalıştıktan 15-20 saniye sonra tekrar çalıştırmayı deneyin (garip bir şekilde “Ad failed to load : 0” hatasını çözebiliyor)(yazının sonunda paylaştığım ReklamScript bunu otomatik olarak yapıyor; reklam yüklenmezse 30 saniye sonra tekrar deniyor). Bir fonksiyonu gecikmeli çağırmak için Invoke veya StartCoroutine kullanabilirsiniz
  • Uygulamanızı imzalayıp öyle build almayı deneyin (imzalama konusunda kısa bir rehber için: https://yasirkula.com/2014/04/17/unity-android-oyununuzu-google-playe-yuklemek/)
  • Android cihazınızın reklam kimliğini sıfırlamayı deneyin (“android reklam kimliğini sıfırla” şeklinde arama yapabilirsiniz)
  • Eğer uygulamanızı çoktan Google Play’de yayımladıysanız ama Google Play sayfasında “Fiyatlandırma ve dağıtım” kısmında yer alan “Reklam içerir” sorusunu “Hayır” olarak işaretlediyseniz, o seçeneği “Evet” yapın
  • logcat kullanarak bir hata alıp almadığınıza bakın. Örneğin bende rewarded video reklamlar çok ender gözüküyor ve genel olarak da fillrate hatası alıyorum, yani sunucuda herkese yetecek kadar reklam olmaması hatası. Bu gibi durumlarda elden bir şey gelmiyor maalesef (sadece Admob ile alakalı log’ları görmek için “adb logcat -s Ads” (tırnaksız) komutunu kullanabilirsiniz, ilaveten “adb logcat -s Unity” ile de Unity’nin bir hata verip vermediğine bakabilirsiniz). Reklamlarla ilgili bir sorun yaşarsanız, logcat’ten sorunun kaynağını tespit etmeye çalışıp sorunu internette hızlıca bir arayın
  • Yaşadığınız sorunlar için AdMob forumlarında konu açarak da AdMob ekibinden ve diğer AdMob kullanıcılarından yardım alabilirsiniz:

Test Reklamları ( **ÖNEMLİ** )

Kendi reklam kimlikleriniz ile reklamları test ederken cihazınızı test cihazı olarak tanıtmazsanız, Admob servisinden banlanabilirsiniz. Bu durumu engellemek ve oyunu kendi telefonunuzdan test ederken reklamların para kazandırmasını önlemek için izleyebileceğiniz iki yol var:

  • Admob’un Test İçin Olan Reklam Kimliklerini Kullanmak

Admob her reklam türü için birer adet test reklam kimliği sunmakta. Yukarıdaki script’lerde yer alan reklam kimlikleri de işte bu kimlikler. Bu kimlikleri kullanan reklamları test esnasında dilediğinizce gösterebilir, reklamlara tıklayabilirsiniz. Bu kimliklerin bir başka avantajı da, uygulamanızda bir türlü reklam gösteremediğiniz durumlarda, sorunun sizin reklam kimliklerinizden mi kaynaklandığını tespit etmek için kullanılabilmeleridir. Eğer kendi reklam kimliklerinizi kullanırken reklam gelmiyor ama test reklam kimliklerini kullanırken geliyorsa sorun sizin reklam kimliklerinizdedir; her iki durumda da reklam gelmiyorsa sorun Admob entegrasyonunuzdadır.

Güncel test reklam kimlikleri şöyle:

Banner: ca-app-pub-3940256099942544/6300978111

Interstitial: ca-app-pub-3940256099942544/1033173712

Rewarded: ca-app-pub-3940256099942544/5224354917

Tek yapmanız gereken, kodunuzdaki reklam kimlik(ler)ini test aşamasında bu kimlikler ile değiştirmek.

  • Cihazınızda Test Modunu Aktifleştirmek

Bu aşamanın önceki aşamaya göre bir avantajı, direkt kendi reklam kimlikleriniz üzerinden reklamları test edebilmenize olanak sağlamasıdır. Ayrıca test reklam kimliklerinin aksine, bu modda gösterilen reklamlar gerçek reklamlardır. Bu modda bir reklama tıkladığınızda para kazanmazsınız.

Cihazınız için test modunu aktifleştirebilemek için öncelikle cihazınızın özgün ID’sini bulmanız lazım. Bunun en garanti yolu da adb logcat kullanmak. İşinizi garantiye almak ve ban riskini önlemek için, öncelikle kodunuzdaki reklam kimliklerini yukarıdaki test reklam kimlikleri ile değiştirin ve ardından konsoldan adb logcat -s Ads komutunu çalıştırın. Uygulama esnasında reklam gösterirken logcat konsoluna şuna benzer log’lar gelecek:

RequestConfiguration.Builder.setTestDeviceIds(Arrays.asList(“CİHAZ_IDSİ”)) (Dipnot: bu log emülatörlerde gözükmeyebilir çünkü onlar için test modu otomatik olarak aktiftir).

Yapmanız gereken, reklam kodunuzun Start fonksiyonuna şu kodu eklemek:

RequestConfiguration reklamKonfigurasyonu = new RequestConfiguration();
reklamKonfigurasyonu.TestDeviceIds.Add("CİHAZ_IDSİ");

MobileAds.SetRequestConfiguration( reklamKonfigurasyonu );

Artık kendi reklam kimliklerinizi kullanabilirsiniz. Bundan böyle reklamlarınızın üzerinde ufak bir “Test Ad” yazısı gözükecek ve reklamlarınıza rahatlıkla tıklayabileceksiniz (bazen emülatörde interstitial reklam test ederken “Test Ad” yazısını görmüyorum, bu bir hata mı bilmiyorum ama “Test Ad” yazısı görmediğiniz zaman ne olur ne olmaz reklama tıklamamanızı öneririm).

Gelişmiş Özellikler

a) Banner Reklamlar

Şimdi dilerseniz, reklamlarla yapabileceklerimizi görmek amaçlı scriptlerimizi birazcık daha geliştirelim. Yapmak istediğimiz şey şu: banner reklam her iki saniyede bir belirip kaybolsun. Böylece istediğimiz zaman reklamı gizlemeyi, istediğimiz zaman geri getirmeyi göreceğiz.

using UnityEngine;
using GoogleMobileAds.Api;
 
public class ReklamBanner : MonoBehaviour
{
	private float reklamBelirmeAni;
	private bool reklamDurumu = false;
	private BannerView reklamObjesi;
 
	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		reklamBelirmeAni = Time.time + 2f;
		
		reklamObjesi = new BannerView( "ca-app-pub-3940256099942544/6300978111", AdSize.Banner, AdPosition.Top );
		AdRequest reklamIstegi = new AdRequest();
		reklamObjesi.LoadAd( reklamIstegi );
	}
	
	void Update()
	{
		if( Time.time >= reklamBelirmeAni )
		{
			reklamBelirmeAni = Time.time + 2f;
			reklamDurumu = !reklamDurumu;

			if( reklamDurumu )
				reklamObjesi.Show();
			else
				reklamObjesi.Hide();
		}
 
	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

Update fonksiyonunda iki saniyede bir reklamDurumu‘nun değerini değiştiriyoruz ve değeri true ise reklamı Show() fonksiyonu ile gösteriyor, false ise Hide() fonksiyonuyla gizliyoruz. Bu kadar basit!

Burada şöyle bir ilave bilgi de vereyim: banner reklam objeleri scene geçişlerinden etkilenmez. Bu yüzden eğer bir banner reklamı diğer sahneye geçmeden önce gizlemezseniz, o reklam diğer sahnede de görünür halde olur.

Ayrıca madem bahsi geçmiş, tekrar hatırlatayım: eğer bir reklamla işiniz kesinlikle bittiyse, Destroy fonksiyonuyla o reklamın hafızada kapladığı yeri boşaltın. Örneğin A sahnesinde banner reklam gösteriyorsanız ama bu banner reklama B sahnesinde ihtiyacınız yoksa, A’dan B’ye geçmeden önce reklamObjesi.Destroy(); fonksiyonunu çağırın.

b) Interstitial Reklamlar

Eğer siz de Interstitial reklamları test ettiyseniz fark etmişsinizdir: reklamların yüklenmesi uzun sürebiliyor. Bunun için benim düşündüğüm yöntem, oyunun en başında reklam değişkeninde bir tane Interstitial reklamı hazır bulundurmak. Bu reklamı kullanıcıya gösterdikten ve kullanıcı reklamı kapattıktan hemen sonra ise yeni bir reklam alıp artık bu yeni reklamı değişkende depolamak. Böylece reklamlar, onları göstermek istediğimiz zaman elimizde hazır olacak ve reklamın gözükmesi için daha az bekleyeceğiz. Buna ilaveten, reklam yüklenene kadar ekrandaki “Reklamı Göster” butonunu inaktif yapalım. ReklamInterstitial scriptini şöyle değiştirin:

using UnityEngine;
using System.Collections;
using GoogleMobileAds.Api;
 
public class ReklamInterstitial : MonoBehaviour
{
	private InterstitialAd reklamObjesi;
 
	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		YeniReklamAl();
	}
 
	// Ekranda test amaçlı "Reklamı Göster" butonu göstermeye yarar, bu fonksiyonu silerseniz buton yok olur
	void OnGUI()
	{
		GUI.enabled = reklamObjesi != null && reklamObjesi.CanShowAd();
		
		if( GUI.Button( new Rect( Screen.width / 2 - 150, Screen.height - 300, 300, 300 ), "Reklamı Göster" ) )
		{
			reklamObjesi.Show();
		}
		
		GUI.enabled = true;
	}
	
	void YeniReklamAl()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
		
		AdRequest reklamIstegi = new AdRequest();
		InterstitialAd.Load( "ca-app-pub-3940256099942544/1033173712", reklamIstegi, ( InterstitialAd _reklamObjesi, LoadAdError hata ) =>
		{
			// Eğer reklam yüklenemezse bir hata mesajı log'la
			if( hata != null || _reklamObjesi == null )
			{
				Debug.LogError( "Interstitial reklam yüklenemedi: " + hata );
				return;
			}

			reklamObjesi = _reklamObjesi;
			reklamObjesi.OnAdFullScreenContentClosed += () => YeniReklamAl(); // Kullanıcı reklamı kapattıktan sonra çağrılır
			reklamObjesi.OnAdFullScreenContentFailed += (AdError error) => YeniReklamAl(); // Reklam gösterim esnasında bir hata olursa çağrılır
		} );
	}
 
	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

c) Rewarded Video Reklamlar

Tıpkı üstteki interstitial kodunda olduğu gibi, rewarded video reklamın da oyunun en başında yüklenmesini sağlayalım. Kullanıcı reklamı kapattıktan sonra da otomatik olarak yeni bir video reklamı yükleyip hazırda bulunduralım. reklamObjesi‘nin CanShowAd() fonksiyonunu kullanarak, ekrandaki reklamı göstermeye yarayan butonun sadece reklam sunucudan tamamen indirilmişse tıklanabilir olmasını sağlayalım. Son olarak da, kullanıcı rewarded videoyu baştan sona izlerse ona ödül olarak 100 altın verelim:

using UnityEngine;
using System.Collections;
using GoogleMobileAds.Api;

public class ReklamRewardedVideo : MonoBehaviour
{
	private int altin = 0;
	private RewardedAd reklamObjesi;

	void Start()
	{
		MobileAds.Initialize( AdMobHazirlandi );
	}
	
	void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		YeniReklamAl();
	}

	// Ekranda test amaçlı "Reklamı Göster" butonu göstermeye yarar, bu fonksiyonu silerseniz buton yok olur
	void OnGUI()
	{
		GUI.Box( new Rect( 0, Screen.height / 2, 500, 150 ), altin + " altının var!" );

		string butonMetin;
		if( reklamObjesi != null && reklamObjesi.CanShowAd() )
		{
			// Reklam gösterime hazır. Reklama AdMob konsolundan atanan ödülün (Reward) ne kadar olduğunu öğren
			butonMetin = reklamObjesi.GetRewardItem().Amount + " altın kazan!";
		}
		else
		{
			butonMetin = "Reklam yükleniyor...";

			// Reklam henüz yüklenmemiş. Butonu tıklanamaz yap
			GUI.enabled = false;
		}

		if( GUI.Button( new Rect( Screen.width / 2 - 150, 0, 300, 300 ), butonMetin ) )
			reklamObjesi.Show( OyuncuyuOdullendir );

		GUI.enabled = true;
	}
	
	void YeniReklamAl()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}

		AdRequest reklamIstegi = new AdRequest();
		RewardedAd.Load( "ca-app-pub-3940256099942544/5224354917", reklamIstegi, ( RewardedAd _reklamObjesi, LoadAdError hata ) =>
		{
			// Eğer reklam yüklenemezse bir hata mesajı log'la
			if( hata != null || _reklamObjesi == null )
			{
				Debug.LogError( "Rewarded reklam yüklenemedi: " + hata );
				return;
			}

			reklamObjesi = _reklamObjesi;
			reklamObjesi.OnAdFullScreenContentClosed += () => YeniReklamAl();
			reklamObjesi.OnAdFullScreenContentFailed += (AdError error) => YeniReklamAl();
		} );
	}
	
	void OyuncuyuOdullendir( Reward odul )
	{
		Debug.Log( "Ödül türü: " + odul.Type );
		altin += (int) odul.Amount;
	}

	void OnDestroy()
	{
		if( reklamObjesi != null )
		{
			reklamObjesi.Destroy();
			reklamObjesi = null;
		}
	}
}

Burada OyuncuyuOdullendir fonksiyonuna parametre olarak gelen Reward türündeki odul değişkeni, siz ödüllü reklamı Admob üzerinde oluştururken girdiğiniz “Ödül miktarı” (odul.Amount) ve “Ödül öğesi” (odul.Type) değerlerini depolamakta. Ben kendi reklamımı oluştururken “Ödül miktarı“nı 100 girmiştim ve bu yüzden altin değişkenim her seferinde 100 artıyor. Daha önceden de bahsettiğim gibi, burada işin güzel yanı, bu Reward parametrelerini oyunu güncellemeye gerek kalmadan direkt olarak Admob panelinden güncelleyebiliyorsunuz. Eğer ödül miktarına reklamı göstermeden önce erişmek isterseniz (mesela ödüllü reklam butonunda ödül miktarının ne kadar olduğunu belirtmek için), reklamObjesi‘nin GetRewardItem fonksiyonunu çağırabilirsiniz. Bildiğim kadarıyla bunun için reklamın sunucudan tamamen indirilmiş olması lazım, yani CanShowAd() true döndürmeli.

Ekstralar

1) Reklamı Kişiselleştirmek

Eğer ki yaptığınız oyun çocuklara yönelik ise ve(ya) oyununuzu Google Play‘e koyarken “Designed for Families” programına katılmayı seçerseniz, o zaman oyununuzda çocuklara yönelik reklamlar sunabilmeniz ve daha da önemlisi, reklamlarınızın görünebilmesi için kodda ufak bir değişiklik yapmanız gerekmekte:

void Start()
{
	RequestConfiguration reklamKonfigurasyonu = new RequestConfiguration();
	reklamKonfigurasyonu.TagForChildDirectedTreatment = TagForChildDirectedTreatment.True;
    MobileAds.SetRequestConfiguration( reklamKonfigurasyonu );

	MobileAds.Initialize( AdMobHazirlandi );
}

Çocuklara yönelik reklamlarda bilmeniz gereken iki husus var:

  • Çocuklara yönelik reklam veren daha az firma olduğu için, eğer bir reklam isteği yolladığınız anda AdMob sunucularında çocuklara yönelik reklam kalmadıysa o reklam gözükmez
  • Oyununuzun Google Play’e kabul edilebilmesi için, oyun başlar başlamaz (oyun ilk açıldığında) interstitial reklam göstermemeye ve aynı anda birden çok reklam göstermemeye (mesela 2 banner reklam) özen göstermeniz gerekiyor (kaynak: https://play.google.com/about/families/ads-monetization/)

Çocuklara yönelik reklamlardan farklı olarak, dilerseniz göstermek istediğiniz reklamın hedef kitle etiketini de belirleyebilirsiniz. Örneğin hedef kitle yaşınıza en çok PG etiketi uyuyorsa, reklam kodunuzu şu şekilde güncelleyebilirsiniz:

void Start()
{
	RequestConfiguration reklamKonfigurasyonu = new RequestConfiguration();
	reklamKonfigurasyonu.MaxAdContentRating = MaxAdContentRating.G;
    MobileAds.SetRequestConfiguration( reklamKonfigurasyonu );

	MobileAds.Initialize( AdMobHazirlandi );
}

Bu arada belirtmeden geçmeyeyim, RequestConfiguration’a birden çok değişikliği aynı anda uygulamanız mümkün. Örneğin hem SetTestDeviceIds hem de yukarıdaki fonksiyon(lar)ı kullanmak istiyorsanız:

void Start()
{
	RequestConfiguration reklamKonfigurasyonu = new RequestConfiguration();
	reklamKonfigurasyonu.TagForChildDirectedTreatment = TagForChildDirectedTreatment.True;
	reklamKonfigurasyonu.MaxAdContentRating = MaxAdContentRating.PG;
	reklamKonfigurasyonu.TestDeviceIds.Add("CİHAZ_IDSİ");
    MobileAds.SetRequestConfiguration( reklamKonfigurasyonu );

	MobileAds.Initialize( AdMobHazirlandi );
}

2) Unity Ads Entegrasyonu (Mediation)

Bu kısım güncel değildir, hatalı kısımlar olabilir. Resmî dokümantasyonu referans alınız: https://developers.google.com/admob/unity/mediation

Admob’un özellikle rewarded video reklamlarda reklam havuzu zaman zaman yetersiz kalmakta ve fillrate hatası döndürmektedir. Bu tarz bir durumla daha az karşılaşmak (daha geniş bir reklam havuzuna sahip olmak) için, mediation denen sistem vasıtasıyla, uygulamalarınızda Admob’un reklamlarına ilaveten diğer popüler reklam firmalarının reklamlarını da gösterebilirsiniz.

Mediation’da bilinmesi gereken önemli bir nokta, mediation ile gösterilen reklamların ödemesi, Admob tarafından değil de mediation’ı yapılan firma tarafından sağlanır. Yani Unity Ads mediation’ı yaparsanız, uygulamanızda gösterilen Unity Ads reklamlarının gelirlerini Admob’dan değil Unity Ads’ten alırsınız ve bunun için ödeme bilgilerinizin Unity Ads’te yer alması gereklidir. Ben nasıl ödeme bilgilerinizi Unity Ads’e ekleyebileceğinizden de burada basitçe bahsedeceğim ancak şunu baştan bilin: Unity Ads’ten ödeme alabilmek için, SWIFT para transferi destekleyen bir banka hesabınızın olması lazım. Eğer henüz böyle bir banka hesabınız yoksa, hesap açana kadar paranın Unity Ads hesabınızda birikmesini talep etmeniz de mümkün.

Unity Ads mediation’ı banner, interstitial ve rewarded video reklamları desteklemektedir. Mediation’a başlamadan önce, Admob’da tanımlı banner/interstitial/rewarded video reklam kimlikleriniz olmalıdır. Mediation’ını bu reklam kimliklerinin üzerine uygulayacaksınız.

Faydalanılan kaynak: https://developers.google.com/admob/unity/mediation/unity

Öncelikle https://dashboard.unityads.unity3d.com/ adresine gidin, soldan Projects sekmesine geçiş yapın ve New Project butonuna tıklayın. “Project name“e projenizin ismini girin ve eğer uygulamanız özellikle 13 yaş altı çocuk kitlesine hitap ediyorsa, “This game is directed to children under the age of 13 in the United States” seçeneğini işaretleyin. “App Store ID“leri şimdilik boş bırakabilirsiniz. İşlemi tamamlamak için Add project butonuna tıklayın.

Reklam kimlikleri oluşturmak için projenizin ana sayfasında sol tarafta yer alan menüden Monetization-Placements yolunu izleyin ve Add Placement butonuna tıklayın. “Placement ID“e reklam kimliği için bir isim girin ve eğer banner reklam kimliği oluşturuyorsanız Banner, interstitial reklam kimliği oluşturuyorsanız Interstitial video, yoksa Rewarded video seçeneğini seçip Create Placement butonuna tıklayarak işlemi sonlandırın:

Unity Ads mediation’ınınızda not almanız gereken üç farklı değer var:

  • Reklam kimlik(ler)inizin “Placement ID”(ler)i: oluşturduğunuz bir reklam kimliğine tıklayınca gelen sayfadan öğrenebilirsiniz
  • GAME ID: sol taraftan Settings-Project Settings sekmesine geçiş yapınca “Google Play Store” satırında yer alır
  • API Key: sol üstten All projects‘e tıkladıktan sonra Ad Data Export-API Access yolunu izleyince gelen ekrandan öğrenilebilir

Artık Unity Ads reklam kimliklerini mediation vasıtasıyla Admob’a tanıtabiliriz. Bunun için şu yolu izleyebilirsiniz:

  • Admob hesabınıza giriş yaptıktan sonra soldan Uyumlulaştırma sekmesine geçiş yapıp UYUMLULAŞTIRMA GRUBU OLUŞTUR butonuna tıklayın
  • Reklam biçimi” olarak banner reklam için Banner, interstitial reklam için Geçiş, Rewarded video reklam için Ödüllü seçeneğini seçip DEVAM‘a tıklayın
  • Mediation için bir Ad girin
  • REKLAM BİRİMİ EKLE butonuna tıklayın ve Admob üzerinde halihazırda var olan ilgili reklam kimliğinizi seçip TAMAMLANDI‘ya tıklayın
  • Şelale reklam kaynakları bölümünde yer alan REKLAM KAYNAĞI EKLE butonuna tıklayıp Unity Ads‘i seçin (eğer bulamazsanız arama kısmına Unity Ads yazabilirsiniz)
  • API Key‘i Unity Ads’ten aldığınız key ile doldurup Yetkilendirme kutucuğunu işaretleyin
  • eBGBM kısmına bir değer girin (ben henüz bu konuda tecrübeli değilim, o yüzden buraya temsili olarak 2 girdim) ve DEVAM‘a tıklayın
  • Game ID ve Placement ID‘leri Unity Ads’ten aldığınız ID’lerle doldurup TAMAMLANDI butonuna tıklayın
  • KAYDET butonuna tıklayarak mediation (uyumlulaştırma) grubunuzu kaydedin

Eğer birden çok reklam türü için (banner, interstitial, rewarded video) Unity Ads mediation’ı ekleyecekseniz, tahmin edeceğiniz üzere her bir reklam türü için ayrı bir uyumlulaştırma grubu oluşturmalısınız.

NOT1: eğer rewarded video reklam için mediation uyguluyorsanız, Admob’daki rewarded video reklam kimliğinizin Ödül ayarları‘ndaki “Uyumlulaştırma grubundaki tüm ağlara uygula” seçeneğinin seçili olduğundan emin olun.

NOT2: uygulamanızı test ederken Unity Ads’ten de test reklamları almak için, Unity Ads arayüzündeki Settings-Project Settings sayfasından Test Mode satırının yanında yer alan “Google Play Store“a tıklayın, Override client test mode seçeneğini aktifleştirin ve “Force test mode ON“u işaretleyip Save butonuna tıklayın. Maalesef Admob kodunuz test modunda olsa bile bu ayar otomatik olarak Unity Ads’e işlemiyor, o yüzden böyle bir prosedür işliyoruz. Yalnız uygulamanızı yayınladıktan sonra override client test mode‘u kapatmayı unutmayın! Test moduna yapılan değişikliklerin reklamlara yansıması biraz vakit alabilir, o yüzden hemen niye olmuyor bu demeyin.

NOT3: uygulamanızı yayımladıktan sonra, Settings-Project Settings‘ten Store IDs satırının yanında yer alan “Google Play Store“un sağındaki Add Store Id butonuna tıklayarak, mağazadaki uygulamanızı Unity Ads’e bağlayabilirsiniz. Diyelim uygulamanızın store linki https://play.google.com/store/apps/details?id=com.unity3d.genericremote ise, ID’niz com.unity3d.genericremote‘tur. Bazı reklam sağlayıcıları, bu ID’yi girmezseniz size reklam sağlamıyor(muş). Eğer oyununuzu daha yeni yayımladıysanız, oyununuzun Add Store Id tarafından tanınması 1 hafta kadar sürebilir.

Geriye sadece Unity Ads mediation’ı için gerekli şeyleri Unity’e import etmek kaldı. Bunun için şu adresteki en güncel versiyonun zip‘ini indirin: https://bintray.com/google/mobile-ads-adapters-unity/GoogleMobileAdsUnityAdsMediation#files

Zip’in içindeki unitypackage’ı dışarı çıkarıp Unity’e import edin (Assets-Import Package-Custom Package…). Ardından emin olmak için bir kere daha Play Services Resolver-Android Resolver-Resolve yapın. İşte bu kadar! Artık Admob reklam havuzunda reklam yoksa, otomatik olarak Unity Ads reklam havuzundan reklam çekilecek. Bu reklamların ödemesi ise Unity Ads tarafından sağlanacak.

O halde gelelim Unity Ads reklamlarının ödemesini alabilmek için ödeme bilgilerimizi girmeye. https://id.unity.com adresine giriş yapın ve soldan Organizations butonuna tıklayıp hesabınızı seçin. Ardından yine soldan Payout Profile sayfasına geçiş yapıp Add profile butonuna tıklayın. Eğer oyununuzu bir şirket ile değil de tek başınıza yaptıysanız “Payment recipient is“i Private individual yapın. Sonra diğer istenen bilgileri de doldurup Create butonuna tıklayın. “Full Name” ile ilgili bir hata alırsanız, isminizde Türkçe karakter kullanmayın.

Ödeme bilgilerinizi girmeden önce, vergi bilgilerinizi girmek için Payout Tax Info‘nun yanındaki Create butonuna tıklayın. Buradan sonra, sizden adım adım bir takım bilgiler girmeniz istenecek. Doğruya doğru, bu kısım gerçekten biraz karışık. Bu yüzden bu esnada yanınızda, İngilizce’den anlayan ve mümkünse daha önce bu tarz işlerle uğraşmış birinin olması oldukça işinize yarayacaktır.

Vergi işlemlerini tamamladıktan sonra artık ödeme bilgilerinizi girebilirsiniz. Bunun için Payout Method‘daki Add payout method butonuna tıklayın. Eğer henüz SWIFT para transferi destekleyen bir hesabınız yoksa, paranın Unity Ads hesabınızda birikmesi için “Hold my payments“ı seçin ve işlemi tamamlayın. Aksi taktirde “Bank transfer” seçeneğini seçin. Minimum Payout Amount, Unity Ads hesabınızda ne kadar para biriktikten sonra, bu paranın bankanıza aktarılacağıdır. Ancak uluslararası para transferi demek aynı zamanda bankanın bundan komisyon alması da demek olduğu için (ilaveten Unity de 7.5 euro komisyon alıyor), transfer sayısını minimuma indirmek adına bu değeri yüksek tutmanızı öneririm. Sonrasında Add bank transfer details butonu ile, banka bilgilerinizi Worldpay sistemi üzerinden girebilirsiniz. Bankanızın SWIFT bilgilerini, bankanın web sitesi üzerinden bulmanız mümkün. Banka bilgilerinizi de girdikten sonra artık yapmanız gereken bir şey kalmıyor.

3) app-ads.txt Entegrasyonu

Bu kısım güncel değildir, hatalı kısımlar olabilir.

Admob’un dokümantasyonunda yazdığına göre, bu sistem daha güvenli bir şekilde reklam alabilmemize yardımcı oluyormuş. Daha önceden Admob hesabı açtı idiyseniz de zaten birkaç defa app-ads.txt konulu mail almışsınızdır. Peki bu sisteme nasıl geçiş yapabiliriz?

app-ads.txt‘yi destekleyebilmek için, oyununuzun Google Play sayfasında Website kısmını web sitenizin url’si ile doldurmanız ve buraya girdiğiniz websitenin host’una erişim imkanınız olması lazım. Çünkü diyelim oraya https://websitem.com girdiyseniz, oluşturacağınız app-ads.txt dosyasını https://websitem.com/app-ads.txt adresine yüklemeniz gerekecek. Eğer henüz oyununuz Google Play’de yayımlanmadıysa, bu işlemi oyunu yayımladıktan sonra da yapabilirsiniz çünkü bu işlem kodda hiçbir değişiklik gerektirmiyor.

Peki websitemize yükleyeceğimiz bu metin dosyasının içeriği ne olacak? Bunun için Admob hesabınıza giriş yapıp soldan Uygulamalar-Tüm uygulamalar yolunu izleyin ve gelen ekrandan APP-ADS.TXT sekmesine geçiş yapın. Burada sağ üstte yer alan APP-ADS.TXT DOSYASINI AYARLAMA butonuna tıklayın. Gelen ekrandaki google.com ile başlayan satırı, app-ads.txt isimli bir metin dosyasının içerisine yapıştırın. Ardından bu metin dosyasını websitenizin root’unda yer alan public-html klasörüne upload edin. Başka bir işlem yapmanız gerekmiyor.

NOT: Unity Ads entegrasyonu yaptıysanız, app-ads.txt dosyasına Unity Ads için de bir takım satırlar eklemelisiniz. Bunun için https://operate.dashboard.unity3d.com/ adresine girip soldan Settings butonuna tıklayın ve App-ads.txt satırının sağında yer alan kutucuktaki tüm metni, app-ads.txt dosyanıza ekleyin:

app-ads.txt dosyanızı doğru bir şekilde oluşturup oluşturmadığınızı doğrulamanın bir yolu var. Oyununuzu Google Play’de yayımladıktan ve app-ads.txt dosyasını sitenize yükledikten birkaç gün sonra, Admob hesabınızdaki APP-ADS.TXT sekmesini ziyaret edin. Oradaki listede oyununuz gözüküyor ve solunda yeşil bir daire yer alıyorsa bir sıkıntı yok demektir. Listede oyun gözüküyor ama solunda kırmızı bir daire varsa ya app-ads.txt dosyasının içeriği yanlıştır ya da dosyayı doğru yere yüklememişsinizdir. Listede oyununuz gözükmüyorsa, birkaç gün daha beklemeniz gerekebilir.

4) GDPR Hakkında

Bu kısım güncel değildir, hatalı kısımlar olabilir. Resmî dokümantasyonu referans alınız: https://developers.google.com/admob/unity/privacy (ayrıca bkz. https://github.com/googleads/googleads-mobile-unity/blob/main/samples/HelloWorld/Assets/Scripts/GoogleMobileAdsConsentController.cs)

GDPR, Avrupa Birliği vatandaşlarının kişisel verilerinin izinsiz olarak işlenmesini yasaklayan bir yönetmeliktir. Reklam firmaları, gösterdikleri reklamların tıklanma oranlarının fazla olması için kişilerin özel verilerinden faydalanmayı çok severler. Ama GDPR ile, Avrupa Birliği vatandaşları size bilinçli olarak izin vermedikleri sürece onların verilerini toplamanız ve reklam firmaları ile paylaşmanız yasaktır. Burada benim gördüğüm kadarıyla 2 seçeneğiniz bulunuyor:

  1. AdMob’a, Avrupa Birliği vatandaşlarından hiçbir şekilde kişisel veri toplamamasını söylemek. Bunun için AdMob konsolundan “Engelleme kontrolleri-AB kullanıcı izni-Göstermek istediğiniz reklamların türünü seçin“in değerini “Kişiselleştirilmemiş reklamlar” yapabilirsiniz.
  2. Avrupa Birliği vatandaşlarına, kişiselleştirilmiş reklamlar görmeye rızaları olup olmadığını sormak (artık bunu nasıl yapacağınız size kalmış, şunun gibi hazır plugin’ler kullanabilir veya kendi UI’ınızı oluşturabilirsiniz) ve bu tercihi AdMob’a iletmek. Daha fazla bilgi için AdMob’un dokümantasyonuna bakabilirsiniz: https://developers.google.com/admob/unity/eu-consent

5) Singleton Reklam Scripti

Admob dersim şimdiye kadar tahminimden çok daha fazla ilgi gördü. Ben de boş durmadım ve hem banner, hem interstitial, hem de rewarded reklamları bir arada destekleyen ve singleton pattern kullanan örnek bir script yazarak işinizi kolaylaştırmak istedim.

Oyunun ilk sahnesinde boş bir GameObject oluşturup içine aşağıdaki ReklamScript C# scriptini atın (scripti kameraya atmayın, içinde Transform hariç başka component olmayan boş bir objeye atın!):

using GoogleMobileAds.Api;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReklamScript : MonoBehaviour
{
	private static ReklamScript instance = null;

	[Header( "Kimlikler" )]
	public string bannerKimligi = "";
	public string interstitialKimligi = "";
	public string rewardedVideoKimligi = "";

	[Header( "Test Modu" )]
	public bool testModu = false;
	public string testDeviceID = "";

	[Header( "Diğer Ayarlar" )]
	public bool cocuklaraYonelikReklamGoster = false;
	public AdPosition bannerPozisyonu = AdPosition.Top;

	private BannerView bannerReklam;
	private InterstitialAd interstitialReklam;
	private RewardedAd rewardedVideoReklam;

	private float interstitialIstekTimeoutZamani;
	private float rewardedVideoIstekTimeoutZamani;

	private float bannerOtomatikYeniIstekZamani = float.PositiveInfinity;
	private float interstitialOtomatikYeniIstekZamani = float.PositiveInfinity;
	private float rewardedVideoOtomatikYeniIstekZamani = float.PositiveInfinity;

	private IEnumerator interstitialGosterCoroutine;
	private IEnumerator rewardedVideoGosterCoroutine;
	
	public delegate void RewardedVideoOdul( Reward odul );
	private RewardedVideoOdul odulDelegate;

	private void Awake()
	{
		if( instance == null )
		{
			instance = this;
			DontDestroyOnLoad( this );

			bannerKimligi = bannerKimligi.Trim();
			interstitialKimligi = interstitialKimligi.Trim();
			rewardedVideoKimligi = rewardedVideoKimligi.Trim();
			testDeviceID = testDeviceID.Trim();

			RequestConfiguration reklamKonfigurasyonu = new RequestConfiguration();

			if( testModu && !string.IsNullOrEmpty( testDeviceID ) )
				reklamKonfigurasyonu.TestDeviceIds.Add( testDeviceID );

			if( cocuklaraYonelikReklamGoster )
				reklamKonfigurasyonu.TagForChildDirectedTreatment = TagForChildDirectedTreatment.True;

			MobileAds.SetRequestConfiguration( reklamKonfigurasyonu );
			MobileAds.Initialize( AdMobHazirlandi );
		}
		else if( this != instance )
			Destroy( this );
	}
	
	private void AdMobHazirlandi( InitializationStatus reklamDurumu )
	{
		BannerReklamYukle();
		InterstitialReklamYukle();
		RewardedReklamYukle();
	}

	private void Update()
	{
		float zaman = Time.realtimeSinceStartup;

		if( zaman >= bannerOtomatikYeniIstekZamani )
		{
			bannerOtomatikYeniIstekZamani = float.PositiveInfinity;
			BannerReklamYukle();
		}

		if( zaman >= interstitialOtomatikYeniIstekZamani )
		{
			interstitialOtomatikYeniIstekZamani = float.PositiveInfinity;
			InterstitialReklamYukle();
		}

		if( zaman >= rewardedVideoOtomatikYeniIstekZamani )
		{
			rewardedVideoOtomatikYeniIstekZamani = float.PositiveInfinity;
			RewardedReklamYukle();
		}
	}

	private bool BannerReklamYukle()
	{
		if( !testModu && string.IsNullOrEmpty( bannerKimligi ) )
			return false;

		if( bannerReklam != null )
		{
			bannerReklam.Destroy();
			bannerReklam = null;
		}
		
		string reklamKimligi;
		if( testModu && ( string.IsNullOrEmpty( testDeviceID ) || string.IsNullOrEmpty( bannerKimligi ) ) )
		{
#if UNITY_ANDROID
			reklamKimligi = "ca-app-pub-3940256099942544/6300978111";
#else
			reklamKimligi = "ca-app-pub-3940256099942544/2934735716";
#endif
		}
		else
			reklamKimligi = bannerKimligi;

		bannerReklam = new BannerView( reklamKimligi, AdSize.Banner, bannerPozisyonu );
		bannerReklam.OnBannerAdLoadFailed += ( LoadAdError hata ) =>
		{
			Debug.LogError( "Banner reklam yüklenemedi: " + hata );
			bannerOtomatikYeniIstekZamani = Time.realtimeSinceStartup + 30f;

			if( bannerReklam != null )
			{
				bannerReklam.Destroy();
				bannerReklam = null;
			}
		};
		
		bannerReklam.LoadAd( ReklamIstegiOlustur() );
		bannerReklam.Hide();
		
		return true;
	}

	private bool InterstitialReklamYukle()
	{
		if( !testModu && string.IsNullOrEmpty( interstitialKimligi ) )
			return false;

		if( interstitialReklam != null && interstitialReklam.CanShowAd() )
			return true;
		
		if( Time.realtimeSinceStartup < interstitialIstekTimeoutZamani )
			return true;
		
		interstitialIstekTimeoutZamani = Time.realtimeSinceStartup + 10f;

		if( interstitialReklam != null )
		{
			interstitialReklam.Destroy();
			interstitialReklam = null;
		}
		
		string reklamKimligi;
		if( testModu && ( string.IsNullOrEmpty( testDeviceID ) || string.IsNullOrEmpty( interstitialKimligi ) ) )
		{
#if UNITY_ANDROID
			reklamKimligi = "ca-app-pub-3940256099942544/1033173712";
#else
			reklamKimligi = "ca-app-pub-3940256099942544/4411468910";
#endif
		}
		else
			reklamKimligi = interstitialKimligi;
		
		InterstitialAd.Load( reklamKimligi, ReklamIstegiOlustur(), ( InterstitialAd reklamObjesi, LoadAdError hata ) =>
		{
			interstitialIstekTimeoutZamani = 0f;
			
			if( hata != null || reklamObjesi == null )
			{
				Debug.LogError( "Interstitial reklam yüklenemedi: " + hata );
				interstitialOtomatikYeniIstekZamani = Time.realtimeSinceStartup + 30f;
				
				return;
			}

			interstitialReklam = reklamObjesi;
			interstitialReklam.OnAdFullScreenContentClosed += () => InterstitialReklamYukle();
			interstitialReklam.OnAdFullScreenContentFailed += ( AdError error ) => InterstitialReklamYukle();
		} );
		
		return true;
	}

	private bool RewardedReklamYukle()
	{
		if( !testModu && string.IsNullOrEmpty( rewardedVideoKimligi ) )
			return false;

		if( rewardedVideoReklam != null && rewardedVideoReklam.CanShowAd() )
			return true;
		
		if( Time.realtimeSinceStartup < rewardedVideoIstekTimeoutZamani )
			return true;
		
		rewardedVideoIstekTimeoutZamani = Time.realtimeSinceStartup + 30f;

		if( rewardedVideoReklam != null )
			rewardedVideoReklam.Destroy();

		string reklamKimligi;
		if( testModu && ( string.IsNullOrEmpty( testDeviceID ) || string.IsNullOrEmpty( rewardedVideoKimligi ) ) )
		{
#if UNITY_ANDROID
			reklamKimligi = "ca-app-pub-3940256099942544/5224354917";
#else
			reklamKimligi = "ca-app-pub-3940256099942544/1712485313";
#endif
		}
		else
			reklamKimligi = rewardedVideoKimligi;
		
		RewardedAd.Load( reklamKimligi, ReklamIstegiOlustur(), ( RewardedAd reklamObjesi, LoadAdError hata ) =>
		{
			rewardedVideoIstekTimeoutZamani = 0f;
			
			if( hata != null || reklamObjesi == null )
			{
				Debug.LogError( "Rewarded reklam yüklenemedi: " + hata );
				rewardedVideoOtomatikYeniIstekZamani = Time.realtimeSinceStartup + 30f;
				
				return;
			}

			rewardedVideoReklam = reklamObjesi;
			rewardedVideoReklam.OnAdFullScreenContentClosed += () => RewardedReklamYukle();
			rewardedVideoReklam.OnAdFullScreenContentFailed += ( AdError error ) => RewardedReklamYukle();
		} );
		
		return true;
	}

	private AdRequest ReklamIstegiOlustur()
	{
		return new AdRequest();
	}

	//private void OnGUI()
	//{
	//  Color c = GUI.color;

	//  if( GUI.Button( new Rect( Screen.width / 2 - 150, 0, 300, 120 ), "Banner Goster" ) )
	//      ReklamScript.BannerGoster();

	//  if( GUI.Button( new Rect( Screen.width / 2 - 150, 120, 300, 120 ), "Banner Gizle" ) )
	//      ReklamScript.BannerGizle();

	//  GUI.color = InterstitialHazirMi() ? Color.green : Color.red;
	//  if( GUI.Button( new Rect( Screen.width / 2 - 150, 240, 300, 120 ), "Interstitial Goster" ) )
	//      ReklamScript.InsterstitialGoster();

	//  GUI.color = RewardedReklamHazirMi() ? Color.green : Color.red;
	//  if( GUI.Button( new Rect( Screen.width / 2 - 150, 360, 300, 120 ), "Rewarded Goster" ) )
	//      ReklamScript.RewardedReklamGoster( null );

	//  GUI.color = c;
	//}

	public static void BannerReklamAl()
	{
		if( instance == null )
			return;

		instance.BannerReklamYukle();
	}

	public static void BannerGoster()
	{
		if( instance == null )
			return;

		if( instance.bannerReklam == null && !instance.BannerReklamYukle() )
			return;

		instance.bannerReklam.Show();
	}

	public static void BannerGizle()
	{
		if( instance == null )
			return;

		if( instance.bannerReklam == null )
			return;

		instance.bannerReklam.Hide();
	}

	public static bool InterstitialHazirMi()
	{
		if( instance == null )
			return false;

		if( instance.interstitialReklam == null )
			return false;

		return instance.interstitialReklam.CanShowAd();
	}

	public static void InterstitialReklamAl()
	{
		if( instance == null )
			return;

		instance.InterstitialReklamYukle();
	}

	public static void InsterstitialGoster()
	{
		if( instance == null )
			return;

		if( instance.interstitialReklam == null && !instance.InterstitialReklamYukle() )
			return;

		if( instance.interstitialGosterCoroutine != null )
		{
			instance.StopCoroutine( instance.interstitialGosterCoroutine );
			instance.interstitialGosterCoroutine = null;
		}

		if( instance.interstitialReklam != null && instance.interstitialReklam.CanShowAd() )
			instance.interstitialReklam.Show();
		else
		{
			instance.interstitialGosterCoroutine = instance.InsterstitialGosterCoroutine();
			instance.StartCoroutine( instance.interstitialGosterCoroutine );
		}
	}

	public static bool RewardedReklamHazirMi()
	{
		if( instance == null )
			return false;

		if( instance.rewardedVideoReklam == null )
			return false;

		return instance.rewardedVideoReklam.CanShowAd();
	}

	public static void RewardedReklamAl()
	{
		if( instance == null )
			return;

		instance.RewardedReklamYukle();
	}

	public static void RewardedReklamGoster( RewardedVideoOdul odulFonksiyonu )
	{
		if( instance == null )
			return;

		if( instance.rewardedVideoReklam == null && !instance.RewardedReklamYukle() )
			return;

		if( instance.rewardedVideoGosterCoroutine != null )
		{
			instance.StopCoroutine( instance.rewardedVideoGosterCoroutine );
			instance.rewardedVideoGosterCoroutine = null;
		}
		
		instance.odulDelegate = odulFonksiyonu;

		if( instance.rewardedVideoReklam != null && instance.rewardedVideoReklam.CanShowAd() )
			instance.rewardedVideoReklam.Show( instance.RewardedVideoOdullendir );
		else
		{
			instance.rewardedVideoGosterCoroutine = instance.RewardedVideoGosterCoroutine();
			instance.StartCoroutine( instance.rewardedVideoGosterCoroutine );
		}
	}

	private IEnumerator InsterstitialGosterCoroutine()
	{
		float istekTimeoutAni = Time.realtimeSinceStartup + 2.5f;
		while( interstitialReklam == null || !interstitialReklam.CanShowAd() )
		{
			if( Time.realtimeSinceStartup > istekTimeoutAni )
				yield break;

			yield return null;
		}

		interstitialReklam.Show();
	}

	private IEnumerator RewardedVideoGosterCoroutine()
	{
		float istekTimeoutAni = Time.realtimeSinceStartup + 10f;
		while( rewardedVideoReklam == null || !rewardedVideoReklam.CanShowAd() )
		{
			if( Time.realtimeSinceStartup > istekTimeoutAni )
				yield break;

			yield return null;
		}

		rewardedVideoReklam.Show( RewardedVideoOdullendir );
	}
	
	private void RewardedVideoOdullendir( Reward odul )
	{
		if( odulDelegate != null )
		{
			odulDelegate( odul );
			odulDelegate = null;
		}
	}
}

Şimdi Inspector’dan Reklam Script‘teki Banner Kimliği, Interstitial Kimliği ve Rewarded Video Kimliği yazan yerlere ilgili kimlikleri yapıştırın. Kullanmadığınız reklam birimlerinin kimliklerini boş bırakabilirsiniz. Eğer Admob’un test reklam kimliklerini kullanarak reklamları test etmek isterseniz Test Modu‘nu aktifleşirin ama Test Device ID‘yi boş bırakın. Bu durumda script otomatik olarak test reklam kimliklerini kullanacak. Eğer cihazda test modunu aktifleştirerek kendi reklam kimlikleriniz üzerinden reklamları test etmek isterseniz de Test Modu‘nu aktifleştirin ve ilaveten Test Device ID‘ye cihaz ID’nizi girin. Oyununuz çocuklara yönelik ise ve(ya) Google Play’de Designed for Families programına katılmayı planlıyorsanız, o zaman Cocuklara Yonelik Reklam Goster seçeneğini işaretleyin; aksi taktirde oyununuzda reklamlar gözükmeyebilir. Son olarak da, Banner Pozisyonu değişkeni vasıtasıyla, banner reklamın ekranda gözükmesini istediğiniz yeri seçin. Varsayılan olarak bu değer AdPosition.Top, yani ekranın tepesidir ancak değerini AdPosition.Bottom yaparsanız banner reklam ekranın altında çıkar. Artık scripti kullanmaya hazırsınız.

Scriptin kullanımı oldukça basit: banner reklamı göstermek için ReklamScript.BannerGoster(); fonksiyonunu, banner reklamı gizlemek için ise ReklamScript.BannerGizle(); fonksiyonunu kullanabilirsiniz.

Interstitial reklam göstermek isterseniz ReklamScript.InsterstitialGoster(); fonksiyonunu kullanmanız yeterli. Eğer o esnada bir interstitial reklam yüklenmişse reklam anında gösterilir, yoksa yeni bir reklam yüklenmeye başlar veya mevcut yüklenmekte olan reklamın yüklenmesi beklenir. Eğer reklam 2.5 saniye içerisinde yüklenirse ekranda gösterilir, yoksa interstitial reklam gösterme isteğiniz başarısız olur. Bunun sebebi ise, reklamın siz bu fonksiyonu çağırdıktan onlarca saniye sonra anca yüklenmesi durumunda, oyunun ortasında *puf* diye ekranda belirerek kullanıcıları kızdırmasının önüne geçmek. Eğer ki sistem üzerinde biraz daha kontrol sahibi olmak isterseniz, ReklamScript.InterstitialHazirMi() fonksiyonu ile interstitial reklamın göstermeye hazır olup olmadığını (yüklenip yüklenmediğini) kontrol edebilir (ve ancak reklam hazırsa göster fonksiyonunu çağırabilir) veya ReklamScript.InterstitialReklamAl() fonksiyonu ile manual olarak bir interstitial reklam yükleme talebinde bulunabilirsiniz. Yüklenen bu reklam arkaplanda ReklamScript.InterstitialGoster() fonksiyonunun çağrılmasını bekler. Aslında singleton kod, sizin bu fonksiyonu çağırmanıza gerek kalmadan, gerektiğinde otomatik olarak yeni bir reklam yüklüyor ancak yine de böyle bir seçeneğiniz olduğunu bilin.

Gelelim rewarded video reklamlara. Kullanıcı bu reklamı baştan sona izlerse kullanıcıyı ödüllendirmek zorunda olduğunuz için, bu reklam biraz daha özel kategoriye giriyor. Rewarded video reklam göstermek için aşağıdaki örnek kodu inceleyebilirsiniz:

using UnityEngine;
 
public class RewardedGosterTest : MonoBehaviour 
{
    private int altin = 0;
 
    void OnGUI()
    {
        if( GUILayout.Button( "Rewarded reklam göster" ) )
        {
            ReklamScript.RewardedReklamGoster( RewardedReklamGosterildi );
        }
    }
 
    void RewardedReklamGosterildi( GoogleMobileAds.Api.Reward odul )
    {
        altin += (int) odul.Amount;
    }
}

Gördüğünüz üzere, rewarded reklam başarılı bir şekilde gösterilirse yapılacak şeyleri RewardedReklamGosterildi isimli, GoogleMobileAds.Api.Reward türünde odul parametresi alan bir fonksiyonda belirliyor ve ReklamScript.RewardedReklamGoster( RewardedReklamGosterildi ); fonksiyonu ile rewarded reklam gösterme talebinde bulunuyoruz. Böylece kullanıcı rewarded video reklamı izledikten sonra RewardedReklamGosterildi fonksiyonu çağrılıyor ve kullanıcı ödüllendiriliyor. Tıpkı interstitial’da olduğu gibi, rewarded reklamda da reklam çağrıldıktan sonra bir timeout mevcut ancak bu değer 2.5 saniye yerine bu sefer 10 saniye çünkü interstitial’ın aksine, genelde rewarded video reklamlar kullanıcının izniyle çağrılır (mesela kullanıcı ‘bedava coin’ butonuna tıklayınca) ve bu durumda kullanıcının 2.5 saniyeden daha uzun bir süre bekletilmesi normaldir. Ancak yine de, sadece bir rewarded reklam hazırda bekliyorsa ‘bedava coin’ butonunu aktifleştirmek istiyorsanız, ReklamScript.RewardedReklamHazirMi() fonksiyonu ile reklamın yüklenip yüklenmediğini kontrol edebilir veya uzun süredir rewarded reklam yüklenmediyse ReklamScript.RewardedReklamAl() fonksiyonu ile manual bir şekilde rewarded reklam talebinde bulunarak tekrar şansınızı deneyebilirsiniz.

Son olarak da, dilerseniz ReklamScript kodundaki OnGUI fonksiyonunun comment’ini kaldırarak reklam birimlerinizi test etmeye yarayan GUI butonlarını ekranda gösterebilirsiniz.

Script singleton’dan faydalandığı için sahne değişse bile yok olmuyor ve böylece bir önceki sahnede tanımladığınız bir reklamın kontrolü bir sonraki sahnede de elinizde oluyor.

Kanımca dersi böylece tamamlamış oldum. Umarım faydalı olmuştur. Başka derslerde görüşmek üzere!

Yorumlar kapalı.