Game crashes after unity ad finished?

I followed unity ads implementation guide. They work as intended in editor. They used to work on phone as well but last few week after ad is finished game crashes.

Test ads are on. Everything in logcat looks normal except: 1

Here is code sample:

`using UnityEngine;
using UnityEngine.Advertisements;
using UnityEngine.UI;

public class RewardedAdsButton : MonoBehaviour, IUnityAdsLoadListener, IUnityAdsShowListener
{
    [SerializeField] Button _showAdButton;
#if UNITY_ANDROID
    [SerializeField] string _androidAdUnitId = "Rewarded_Android";
#elif UNITY_IOS
    [SerializeField] string _iOSAdUnitId = "Rewarded_iOS";
#endif
    public BuildingShutdownPanelScript buildingShutdownPanelScript;
    string _adUnitId = null; // This will remain null for unsupported platforms
    bool showAd = false;
    void Awake()
    {
        // Get the Ad Unit ID for the current platform:
#if UNITY_IOS
        _adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
        _adUnitId = _androidAdUnitId;
#endif

        //Disable the button until the ad is ready to show:
        _showAdButton.interactable = false;
    }
    public void OnEnable()
    {
        if (Advertisement.isInitialized && _showAdButton.interactable != true)
        {
            LoadAd();
        }
    }
    // Load content to the Ad Unit:
    public void LoadAd()
    {
#if UNITY_IOS
        _adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
        _adUnitId = _androidAdUnitId;
#endif
        // IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled in a different script).
        Debug.Log("Loading Ad: " + _adUnitId);
        Advertisement.Load(_adUnitId, this);
    }

    // If the ad successfully loads, add a listener to the button and enable it:
    public void OnUnityAdsAdLoaded(string adUnitId)
    {
        Debug.Log("Ad Loaded: " + adUnitId);

        if (adUnitId.Equals(_adUnitId))
        {
            // Configure the button to call the ShowAd() method when clicked:
            _showAdButton.onClick.AddListener(ShowAd);
            // Enable the button for users to click:
            _showAdButton.interactable = true;
            showAd = false;
        }
    }

    // Implement a method to execute when the user clicks the button:
    public void ShowAd()
    {
        if (!showAd)
        {
            // Disable the button:
            _showAdButton.interactable = false;
            // Then show the ad:
            Advertisement.Show(_adUnitId, this);
            showAd = true;
        }
    }

    // Implement the Show Listener's OnUnityAdsShowComplete callback method to determine if the user gets a reward:
    public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
    {
        if (showAd)
        {
            if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
            {
                Debug.Log("Unity Ads Rewarded Ad Completed");
                // Grant a reward.

                buildingShutdownPanelScript.WatchAd();
                // Load another ad:
                _showAdButton.onClick.RemoveListener(ShowAd);
                Advertisement.Load(_adUnitId, this);

            }
        }

    }

    // Implement Load and Show Listener error callbacks:
    public void OnUnityAdsFailedToLoad(string adUnitId, UnityAdsLoadError error, string message)
    {
        Debug.Log($"Error loading Ad Unit {adUnitId}: {error.ToString()} - {message}");
        // Use the error details to determine whether to try to load another ad.
    }

    public void OnUnityAdsShowFailure(string adUnitId, UnityAdsShowError error, string message)
    {
        Debug.Log($"Error showing Ad Unit {adUnitId}: {error.ToString()} - {message}");
        // Use the error details to determine whether to try to load another ad.
    }

    public void OnUnityAdsShowStart(string adUnitId) { }
    public void OnUnityAdsShowClick(string adUnitId) { }

    void OnDestroy()
    {
        // Clean up the button listeners:
        _showAdButton.onClick.RemoveAllListeners();
    }
}`

I fixed it. Few things someone should check if he has problem with ads. I am using ads 4.1.0 at the moment of writing.


1. There is problem with listeners so you have 2 solutions:

  • Remove listeners completely and use button on click
  • Keep listeners but add bool showAd as I did in code below.

2. OnUnityAdsShowComplete should give award in Coroutine. This was the reason why game crashed.


Code after fixing:

using System.Collections;
using UnityEngine;
using UnityEngine.Advertisements;
using UnityEngine.UI;

public class RewardedAdsButton : MonoBehaviour, IUnityAdsLoadListener, IUnityAdsShowListener
{
    [SerializeField] Button _showAdButton;
#if UNITY_ANDROID
    [SerializeField] string _androidAdUnitId = "Rewarded_Android";
#elif UNITY_IOS
    [SerializeField] string _iOSAdUnitId = "Rewarded_iOS";
#endif
    public BuildingShutdownPanelScript buildingShutdownPanelScript;
    string _adUnitId = null; // This will remain null for unsupported platforms
    private static bool showAd = false;
    void Awake()
    {
        // Get the Ad Unit ID for the current platform:
#if UNITY_IOS
        _adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
        _adUnitId = _androidAdUnitId;
#endif

        //Disable the button until the ad is ready to show:
        _showAdButton.interactable = false;
    }
    public void OnEnable()
    {
        if (Advertisement.isInitialized && _showAdButton.interactable != true)
        {
            LoadAd();
        }
    }
    // Load content to the Ad Unit:
    public void LoadAd()
    {
#if UNITY_IOS
        _adUnitId = _iOSAdUnitId;
#elif UNITY_ANDROID
        _adUnitId = _androidAdUnitId;
#endif
        // IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled in a different script).

        Advertisement.Load(_adUnitId, this);
    }

    // If the ad successfully loads, add a listener to the button and enable it:
    public void OnUnityAdsAdLoaded(string adUnitId)
    {

        if (adUnitId.Equals(_adUnitId))
        {
            // Configure the button to call the ShowAd() method when clicked:
            _showAdButton.onClick.AddListener(ShowAd);
            // Enable the button for users to click:
            _showAdButton.interactable = true;
            showAd = false;
        }
    }

    // Implement a method to execute when the user clicks the button:
    public void ShowAd()
    {
        if (!showAd)
        {
            // Disable the button:
            _showAdButton.interactable = false;
            // Then show the ad:
            Advertisement.Show(_adUnitId, this);
            showAd = true;
        }
    }

    // Implement the Show Listener's OnUnityAdsShowComplete callback method to determine if the user gets a reward:
    public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
    {
        if (showAd)
        {
            if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
            {
                // Grant a reward.
                StartCoroutine(reward());
                // Load another ad:
                _showAdButton.onClick.RemoveListener(ShowAd);
                Advertisement.Load(_adUnitId, this);

            }
        }

    }
    private IEnumerator reward()
    {
        yield return null;
        buildingShutdownPanelScript.WatchAd();
    }
    // Implement Load and Show Listener error callbacks:
    public void OnUnityAdsFailedToLoad(string adUnitId, UnityAdsLoadError error, string message)
    {
        Debug.Log($"Error loading Ad Unit {adUnitId}: {error.ToString()} - {message}");
        // Use the error details to determine whether to try to load another ad.
    }

    public void OnUnityAdsShowFailure(string adUnitId, UnityAdsShowError error, string message)
    {
        Debug.Log($"Error showing Ad Unit {adUnitId}: {error.ToString()} - {message}");
        // Use the error details to determine whether to try to load another ad.
    }

    public void OnUnityAdsShowStart(string adUnitId) { }
    public void OnUnityAdsShowClick(string adUnitId) { }

    void OnDestroy()
    {
        // Clean up the button listeners:
        _showAdButton.onClick.RemoveAllListeners();
    }
}

Hope you find this helpful!