'Unity Ads 4.0 - Multiple OnUnityAdsShowComplete Callbacks for Rewarded ads
Using the Rewarded ad script found on the Unity Ads SDK, I'm running into an issue where the ShowAd() IUnityAdsShowListener => OnUnityAdsShowComplete is firing the debug log incrementally. The first Ad I watch returns one line stating the ad is completed, the second Ad I watch, fires off 2 logs, the third 3, then 4, etc...As if each ShowAd() subscribes a new listener to the callback. is this normal? Im not using a button to call the ShowAd method, rather I'm just calling a function with a delegate from an AdsManager class.
public delegate void OnSuccessfulAd();
private OnSuccessfulAd _myCallback = null;
public void ShowAd(OnSuccessfulAd myMethod)
{
_myCallback = myMethod;
Advertisement.Show(_adUnitId, this);
}
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed"); //Gets called more times each ad
// Grant a reward.
_myCallback?.Invoke();
}
}
Solution 1:[1]
Experiencing the same issue. As a temporary solution I nullify _myCallback after invoking it
Solution 2:[2]
I am working on the Ads 4.0.0 version in Unity.
What I observed even for Button Click is that its giving multiple Logs in Unity Editor.
However if I run the Code in my mobile Build its working as expected only 1 Log gets generated and Reward also remains same on multiple ad watches.
The issues seems to be in the CallBack in unity, My suggestion would be Try the Build in your App Once Hopefully that fixes the issue.
Unity Rewarded Ads Code from Official Page
As Unity has Deprecated most of the Previous Listeners in the New Ads 4.0.0 I think its better to cross check in the Build.
Solution 3:[3]
I was facing the exact same issue.
My OnUnityAdsShowComplete event callback is invoking one of my delegate.
Every references in my delegate was not accessible.
Look like the OnUnityAdsShowComplete is done on a different thread than the main one.
If in your delegate callback you have a simple Time.timeScale=1f, this should cause a crash since Time is no reachable.
Also this has observable only with reward Ads type.
My solution was to call the show() method inside a coroutine.
By having a flag set i.e. isAdRunning
You can poll that flag and when the flag is false isAdRunnin = false then you can call your delegate.
Very annoying.
Here an example. To make the code the simpliest as possible. All the IUnityAds interfaces are in the same class. This is why you will see this as listener arguments.
using UnityEngine.Advertisements;
private bool isAdsRunning = false;
// Ads start callback
public void OnUnityAdsShowStart(string placementId)
{
isAdsRunning = true;
}
// Ads complete callback
public void OnUnityAdsShowComplete(string placementId, UnityAdsShowCompletionState showCompletionState)
{
isAdsRunning = false;
}
// Entry point to show reward ads
public void ShowRewardedAd()
{
StartCoroutine(RewardRoutine());
}
IEnumerator RewardRoutine()
{
while (Advertisement.isShowing)
{
yield return null;
}
// In 4.0 Ads need to be loaded first, after initialization
// just another flag to make sure everything is initialized :)
while (!isAdLoaded)
{
yield return null;
}
// Show Ads
Advertisement.Show(adsUnitIdReward, this);
yield return new WaitForSeconds(0.25f);
while(isAdsRunning)
{
yield return null;
}
// My custom delegate
AdAction.Invoke();
}
Peace and Love.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dmitry K. |
| Solution 2 | Suraj Bhandarkar |
| Solution 3 | Dharman |
