I am a little bit stumped with what seems to be unexpected Unity Ads behaviour to me.
I am expecting to see banner ads in the Play scene if AdsRemoved is set to false (after an IAP made in the Home scene) and if there are fills for the ads, but they are to be hidden in the Home scene. However, a player is seeing a banner ad in the Play scene after purchasing the IAP for AdsRemoved (setting it to true) in the Home scene.
Please see the two script snippets below:
In Play script:
IEnumerator ShowBannerWhenReady() {
while (!Advertisement.IsReady(placementId)) {
yield return new WaitForSeconds(0.5f);
}
Advertisement.Banner.Show(placementId);
}
.
.
.
void Awake() {
.
.
.
#if UNITY_IOS || UNITY_ANDROID
if (!Advertisement.isInitialized) {
Advertisement.Initialize(gameId, testMode);
}
if (!DataHolder.AdsRemoved) {
Advertisement.Banner.SetPosition(BannerPosition.BOTTOM_CENTER);
StartCoroutine(ShowBannerWhenReady());
}
#endif
}
I am rather confused as to why they are still seeing ads. Is it possible that Advertisement.Inistialize automatically shows available placements even without Banner.Show being called, and I need to put it inside the AdsRemoved condition block? Or perhaps I made a mistake somewhere else not mentioned?
For a bit more details, the scenes are loaded with SceneManager.LoadScene, and I made sure DataHolder has loaded the saves of the purchases for AdsRemoved at the beginning of each Awake.
The only thing that springs to mind is if the coroutine starts running before DataHolder.AdsRemoved is set. From what I can see there’s no reason you can’t add an additional check inside ShowBannerWhenReady to make sure DataHolder.AdsRemoved isn’t true when you actually show the banner.
Also, please show your code for AdsRemoved. Are you using PlayerPrefs or other way to persist the purchase state? Or are you checking the IAP receipt during IAP initialization.
AdsRemoved is a bool in the DataHolder which gets serialized and saved to Application.persistentDataPath upon the purchase of the IAP and loaded whenever a scene gets loaded.
Got it, and you’ve confirmed that it works (via debugging) on app restart and app reinstall? What happens to the persistentDataPath storage when the user removes and reinstalls the app?
Yeah, it should’ve been working on restart and reinstall when I last checked. It’s an IAP product so even if they wipe the persistentDataPath file, they could restore purchases.
Edit: I haven’t heard about the issue anymore after implementing kyle-unity’s suggestion.
On iOS, restore is not automatic. When the app starts after a reinstall, the app won’t have info about the prior purchase until they click the Restore button (required by Apple). The user won’t know they need to do this to not see ads, that they have paid for. For Google/Android, you’ll need to ensure that IAP initializes before Ad initialization, and set the flag when the corresponding auto-restore ProcessPurchase is called.
Users can only access the Play scene via the Home scene upon starting the app.
I meant earlier that if I don’t explicitly call Advertisement.Initialize, would it be initialized by simply accessing Advertisement.Banner.isLoaded? If not, wouldn’t InitializePurchasing be called in the Home scene first before Advertisement.Initialize is called in the Play scene?
You need to initialize Advertising before you can call its methods (as far as I know, I support IAP specifically). I don’t know how your scenes are set up, you just need to ensure that IAP is initialized before ads is. Just be sure to fully test the uninstall/reinstall scenario to confirm.