Unity Ad showing multiple times

Hi! I have a problem with Unity Ads. I have a button that starts an ad when clicked on. It seems that the ad is getting started multiple times even though the button registers one click. This leads to the player being rewarded multiple times. Does anyone know what might be causing this issue?

The part of the code I’m using:

 public void Click()
        {
            FindObjectOfType<AudioManager>().Play("Button");
            PlayerPrefs.SetInt("RunsTillCanWatchAd", 3);
            Advertisement.Show("rewardedVideo");
            Debug.Log("Click() called");
        }
  
        public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
        {
            Debug.Log("Ad Finished");
            if(showResult == ShowResult.Finished)
            {
                Debug.Log("Added revive");
                PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") + 1);
            }
            else if(showResult == ShowResult.Skipped)
            {
                Debug.Log("The ad did not finish; skipped");
            }
            else if(showResult == ShowResult.Failed)
            {
                Debug.LogWarning("The ad did not finish due to an error.");
            }
        }

And that’s the log I’m getting:

Thanks for the answers!

The code you showed looked fine and is likely not the problem. It likely has something to do with a a listener being added twice. Possibly your adding one in a start method and you have that script on more than one object, or your enabling and disabling that object causing start to get called more than once. hard to say without seeing more code, but this is where I would focus my debugging at. find all instances of AddListener, and then find all usages of those scripts and see if that helps you narrow down the issue.

3 Likes

Thank you for the quick reply!
This script is present only on the one object, the button itself. I am changing the button’s intractable value though. Here’s the whole script if that helps:

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

public class ReviveHandler : MonoBehaviour, IUnityAdsListener
{
    #region Variebles
    public Sprite redHeart;
    public Sprite whiteHeart;
    public Button bt;
    #endregion

    void Start()
    {
        Advertisement.AddListener(this);
        Advertisement.Initialize("3435969", true);

        if(!PlayerPrefs.HasKey("Revive"))
        {
            PlayerPrefs.SetInt("Revive", 3);
        }

        if(!PlayerPrefs.HasKey("RunsTillCanWatchAd"))
        {
            PlayerPrefs.SetInt("RunsTillCanWatchAd", 0);
        }
    }


    void Update()
    {
        #region DEBUG

        if(Input.GetKeyDown(KeyCode.W))
        {
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") + 1);
        }

        if(Input.GetKeyDown(KeyCode.Q))
        {
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") - 1);
        }
        #endregion

        if((PlayerPrefs.GetInt("RunsTillCanWatchAd") <= 0) && PlayerPrefs.GetInt("Revive") < 5 && Advertisement.IsReady("rewardedVideo"))
        {
            SetSprite(redHeart);
            bt.interactable = true;
        }
        else if(PlayerPrefs.GetInt("Revive") >= 5 || PlayerPrefs.GetInt("RunsTillCanWatchAd") >= 0 || !Advertisement.IsReady())
        {
            SetSprite(whiteHeart);
            bt.interactable = false;
        }
     
    }

    private void SetSprite(Sprite toSet)
    {
        gameObject.GetComponent<Image>().sprite = toSet;
    }

    public void Click()
    {
        FindObjectOfType<AudioManager>().Play("Button");
        PlayerPrefs.SetInt("RunsTillCanWatchAd", 3);
        Advertisement.Show("rewardedVideo");
        Debug.Log("Click() called");
    }

    public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
    {
        Debug.Log("Ad Finished");
        if(showResult == ShowResult.Finished)
        {
            Debug.Log("Added revive");
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") + 1);
        }
        else if(showResult == ShowResult.Skipped)
        {
            Debug.Log("The ad did not finish; skipped");
        }
        else if(showResult == ShowResult.Failed)
        {
            Debug.LogWarning("The ad did not finish due to an error.");
        }
    }
    public void OnUnityAdsReady( string placementId)
    {

    }

    public void OnUnityAdsDidError(string placementId)
    {
        Debug.LogError("Unity Ads error ocured!");
    }

    public void OnUnityAdsDidStart(string placementId)
    {
        Debug.Log("Ad started");
    }
}
1 Like

So I would put a debug.log statement right above AddListener to see if this script is getting called more than once. If it is, fix that. You could also try adding a static bool to gate the addListener and init logic to prevent it from happening more than once.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;
public class ReviveHandler : MonoBehaviour, IUnityAdsListener
{
    #region Variebles
    public Sprite redHeart;
    public Sprite whiteHeart;
    public Button bt;
    #endregion

    private static bool isInitialized = false;
    void Start()
    {
        if (!isInitialized) {
            isInitialized = true;
            Advertisement.AddListener(this);
            Advertisement.Initialize("3435969", true);
        }
        if(!PlayerPrefs.HasKey("Revive"))
        {
            PlayerPrefs.SetInt("Revive", 3);
        }
        if(!PlayerPrefs.HasKey("RunsTillCanWatchAd"))
        {
            PlayerPrefs.SetInt("RunsTillCanWatchAd", 0);
        }
    }
    void Update()
    {
        #region DEBUG
        if(Input.GetKeyDown(KeyCode.W))
        {
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") + 1);
        }
        if(Input.GetKeyDown(KeyCode.Q))
        {
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") - 1);
        }
        #endregion
        if((PlayerPrefs.GetInt("RunsTillCanWatchAd") <= 0) && PlayerPrefs.GetInt("Revive") < 5 && Advertisement.IsReady("rewardedVideo"))
        {
            SetSprite(redHeart);
            bt.interactable = true;
        }
        else if(PlayerPrefs.GetInt("Revive") >= 5 || PlayerPrefs.GetInt("RunsTillCanWatchAd") >= 0 || !Advertisement.IsReady())
        {
            SetSprite(whiteHeart);
            bt.interactable = false;
        }
   
    }
    private void SetSprite(Sprite toSet)
    {
        gameObject.GetComponent<Image>().sprite = toSet;
    }
    public void Click()
    {
        FindObjectOfType<AudioManager>().Play("Button");
        PlayerPrefs.SetInt("RunsTillCanWatchAd", 3);
        Advertisement.Show("rewardedVideo");
        Debug.Log("Click() called");
    }
    public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
    {
        Debug.Log("Ad Finished");
        if(showResult == ShowResult.Finished)
        {
            Debug.Log("Added revive");
            PlayerPrefs.SetInt("Revive", PlayerPrefs.GetInt("Revive") + 1);
        }
        else if(showResult == ShowResult.Skipped)
        {
            Debug.Log("The ad did not finish; skipped");
        }
        else if(showResult == ShowResult.Failed)
        {
            Debug.LogWarning("The ad did not finish due to an error.");
        }
    }
    public void OnUnityAdsReady( string placementId)
    {
    }
    public void OnUnityAdsDidError(string placementId)
    {
        Debug.LogError("Unity Ads error ocured!");
    }
    public void OnUnityAdsDidStart(string placementId)
    {
        Debug.Log("Ad started");
    }
}
6 Likes

This bool gate is just what I needed! Thank you for help. Everything is working fine.

1 Like

It is better practise to use this instead of patching the code with a bool gate.

public void OnDestroy ()
{
Advertisement.RemoveListener (this);
}

Add this to method to your script and the OnUnityAdsDidFinish() will only be called once. (The reason it was called multiple times was because, although the scene changed and a new “IUnityAdsListener” was created, the old “IUnityAdsListener” from the previous scene was still active, resulting to multiple calls of the OnUnityAdsDidFinish() method. An easy way to prove this is to notice that the number of calls of the method is directly proportional with the number of times you changed the scene!)

2 Likes