Showing 2 full screen ads in a row

What is the correct way to show one full screen ad after another? I’m currently having an issue where most of the time the second ad automatically closes straight away, OnUnityAdsDidFinish is called with the result being Skipped. I am testing this on iOS 14.2, built with Unity 2019.4, using 3.5.2 of the Advertisement package.

Here is what I’m currently doing:

  • Adding the listener in Awake and removing the listener in OnDestroy
  • Calling Advertisement.Initialize in Awake, only if isInitialized is false
  • Waiting for Advertisement.IsReady() to be true before calling Advertisement.Show()

Could you post the full code you’re using? Am I right in thinking you want to show two ads back to back with no gap inbetween?

Pretty much yeah. See my code below, I’ve stripped out anything that isn’t relevant.

public void Awake()
{
    this.Initialize();

    Advertisement.AddListener(this);
}

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

private void Initialize()
{
    if (!Advertisement.isInitialized)
    {
        Advertisement.Initialize(gameId.ToString(), !live);
    }
}

public void CheckShouldShowAd(Guid gameId)
{
    this.gameId = gameId;
    this.adAPI.Get(gameId, this.GetCallback);
}

private void GetCallback(HTTPRequest request, HTTPResponse response)
{
    AdCurrencyGetViewModel viewModel = JsonConvert.DeserializeObject<AdCurrencyGetViewModel>(response.DataAsText);
    this.viewModels.Add(viewModel);
}

public void WatchAds(int adsToWatch)
{
    this.adsToWatch = adsToWatch;
    StartCoroutine(this.ShowAd());
}

private IEnumerator ShowAd()
{
    ShowOptions options = new ShowOptions();

    options.gamerSid = this.viewModels[this.adsWatched].Id.ToString();

    while (!Advertisement.IsReady())
    {
        yield return null;
    }

    Advertisement.Show(VideoId, options);

    this.adsWatched++;

    // queue up another ad if applicable
    if (this.adsWatched < MaxAds)
    {
        this.CheckShouldShowAd(this.gameId);
    }
}

private void SubmitWatchedAd(Guid adId, int CurrencyAwarded)
{
    this.adAPI.Post(adId, (request, response) => this.PostCallback(request, response, adId, CurrencyAwarded));
}

private void PostCallback(HTTPRequest request, HTTPResponse response, Guid adId, int CurrencyAwarded)
{
    if (response != null && response.IsSuccess)
    {
        if (this.adsWatched < this.adsToWatch)
        {
            StartCoroutine(this.ShowAd());
        }
        else
        {
            // show error
        }
    }  
    else
    {
        Debug.LogError($"Postcallback error {(response != null ? response.DataAsText : string.Empty)}");
    }
}

// empty OnUnityAdsReady, OnUnityAdsDidError, OnUnityAdsDidStart calls with logging

public void OnUnityAdsDidFinish(string placementId, ShowResult result)
{
    try
    {
        if (result == ShowResult.Finished)
        {
            AdCurrencyGetViewModel viewModel = this.viewModels[this.adsWatched - 1];
            this.SubmitWatchedAd(viewModel.Id, viewModel.CurrencyAward);
        }
        else
        {
            if (result == ShowResult.Skipped)
            {
                Debug.LogWarning("Video was skipped - Do NOT reward the player");
            }
            else if (result == ShowResult.Failed)
            {
                Debug.LogError("Video failed to show");
            }

            this.Complete();
        }
    }
    catch (Exception ex)
    {
        Debug.LogException(ex);
    }
}

Ah, interesting. I think I have an idea of what is happening.

When the Ads SDK shows an ad, it also begins downloading a new ad immediately and this typically finishes before the current ad stops playing. This means your coroutine is probably trying to show a new ad while one is already active (since a new ad is technically “ready” as it has been downloaded), and the SDK auto cancels it with a Skip result.

As well as Advertisement.IsReady() you can also check Advertisement.isShowing which should pause your coroutine until after the first ad finishes. I would strongly recommend also adding a brief delay just to make sure the first ad is fully finished; for example, by using yield new WaitForSeconds(0.1f)

Doing that with a 0.1f second wait afterwards didn’t seem to improve it. I changed that to 1f and that seemed to fix it as far as I can tell. How come this is something that is required? Is it possible to get a better fix for this?

private IEnumerator ShowAd()
        {
            ShowOptions options = new ShowOptions();

            options.gamerSid = this.viewModels[this.adsWatched].Id.ToString();

            while (!Advertisement.IsReady() || Advertisement.isShowing)
            {
                yield return null;
            }

            yield return new WaitForSecondsRealtime(1f);

            Advertisement.Show(VideoId, options);

            this.adsWatched++;

            // queue up another ad if applicable
            if (this.adsWatched < MaxAds)
            {
                this.CheckShouldShowAd(this.gameId);
            }
        }
1 Like

Most of our publishers typically only want to show one ad at a time, so this is all the SDK currently supports. I’ll pass your feedback to the development team.

1 Like