The time has come for putting Ads into the free version of Hamster Chase before its release. Using the AdMob/MobClix plug-in from Prime31, I got things squared away for Android...but what about iOS? Unity has classes that let you implement iAds seamlessly.
In my first iteration, I pretty much copy-pasted the sample code from Unity's documentation. Unfortunately it had some problems:
- Sometimes ads would never appear
- If I did manual positioning, it would never, ever appear.
- If you waited long enough, an ad would be followed by a "non-ad" where the entire ad area turned white.
I tried to figure out what I was doing wrong by digging into the Unity documentation; sadly there was not much description. For instance, would the "visible" property ever be false after I call Show() for any reason? Is it the ad being visible or the view itself? What do I do if the error isn't null? Does it auto-recover? Why just set the banner object to null? What if I made two ADBannerViews? Why use a Coroutine? Which ADBannerView functions are a direct pass-through to Apple's code, versus pass-through-with-internal-Unity-sprinkles in it?
After experimenting, I got an implementation that sort of works. In my implementation:
- Ads will appear and change even after long durations of time, leaving and going back into the game.
- Manual positioning works.
- No "white" ads
Here's the code:
float adTimeInitialized;
bool adsVisible = false;
public void ShowAds()
{
if (!adsVisible)
{
// The Update loop will ensure there is an ad banner
if (null != adBannerView && adBannerView.loaded && null == adBannerView.error) {
adBannerView.Show();
}
adsVisible = true;
}
}
public void HideAds()
{
if (adsVisible)
{
if (null != adBannerView) {
adBannerView.Hide();
}
adsVisible = false;
}
}
void Update()
{
// Ensure there is a banner view if we're trying to show ads
if (adsVisible)
{
if (null == adBannerView)
{
adBannerView = new ADBannerView();
adBannerView.autoSize = false;
adBannerView.currentSizeIdentifier = ADSizeIdentifier.Portrait;
adBannerView.autoPosition = ADPosition.Manual;
// Here's the pinch: No matter what the screen resolution is, iAds
// in landscape mode will always think the screen is 480x320 for iPhones
// and 1024x768 for iPads. So we will use its coordinate system.
adBannerView.position = new Vector2(iAdLogicalScreenWidth - iAdLogicalBannerWidth, 0);
adTimeInitialized = Time.time;
}
if (!adBannerView.loaded && adBannerView.error == null)
{
// Waiting on an ad
if (Time.time - adTimeInitialized > 15)
{
// Waiting too long!
Debug.Log("Ad timeout. Forcing ad reload");
HideAndDestroyAdBannerView();
}
}
else if (null != adBannerView.error)
{
// An error occurred trying to get an ad. Perhaps ad data is not
// available. Try again.
Debug.Log("Killing ad banner (" + adBannerView.error.description + ")");
HideAndDestroyAdBannerView();
}
else
{
// Show the ad
if (!adBannerView.visible) {
Debug.Log("Showing ad banner");
adBannerView.Show();
}
}
}
}
void HideAndDestroyAdBannerView()
{
if (adBannerView.visible) {
adBannerView.Hide();
}
adBannerView = null;
}
A couple things to note about this code, and in general:
- I did not use a Coroutine. I guess I'm just an Update() kinda guy.
- When the adBannerView's error property is not null, I assume it will never work again and set the object to null. Later on, the Update loop replaces it with a new one.
- This code is in a DontDestroyOnLoad object...so the object is never destroyed even when I switch scenes.
- If an ad does not load in 15 seconds, I destroy the banner object and replace it with a new one. They should usually load instantly.
- In the world of iAd, I believe all iPhones are treated as 320x480 and all iPads are 768x1024 in coordinates in portrait mode. It doesn't matter what the actual resolution of your device is. My positioning is weird because I elected to have a portrait-size ad appear in the top corner of my landscape game. I think it looks good this way (though I may decide to center it before the release).
- Despite all my changes, there are periods where ads are simply not rendered on the screen. Apple's documentation suggests this is on purpose to help you test out error conditions. I never have this issue with Prime31's plug-in, but I don't know what Apple has to gain by not showing an ad. If I did the implementation, I would keep the existing ad in play until the next ad loads.
So what to do...stick with ADBannerView or use Prime31? My instincts tell me to start with the ad platform native to the operating system, and that the issues loading ads now are partly by Apple's design and that I should not expect to have these issues in the release (although I probably will so I'll keep an eye on things). However, I can always change my iOS Ad platform to Prime31 down the road.
Comments are welcome!
Citations (Please pay attention to the posting dates as some information may be outdated):
Docs.unity3d.com
Forum.unity3d.com
For apple developers:
Developer.apple.com
WHY THE HECK WOULD WE HELP YOU WITH ADVERTISING! EVERYBODY HATES IT! I HAVE ADBLOCK+ WITH HOW MUCH I HATE ADS
This comment is currently awaiting admin approval, join now to view.
This comment is currently awaiting admin approval, join now to view.