创建控制器前,请先完成 CloudX 和 Google Mobile Ads 初始化。控制器外部仍应保留您现有的频控、重试和广告位触发时机规则。
FirstLookInterstitialController.cs
using System;
using CloudX;
using GoogleMobileAds.Api;
public sealed class FirstLookInterstitialController : IDisposable
{
public enum Source
{
CloudX,
AdMob,
}
public event Action<Source> AdLoaded;
public event Action<Source, string> AdLoadFailed;
public event Action<Source> AdShown;
public event Action<Source, string> AdShowFailed;
public event Action<Source> AdClosed;
public event Action<Source> AdClicked;
private readonly string cloudXAdUnitId;
private readonly string adMobAdUnitId;
private InterstitialAd adMobInterstitial;
private bool isLoadingCloudX;
private bool isLoadingAdMob;
private bool isDisposed;
public FirstLookInterstitialController(
string cloudXAdUnitId,
string adMobAdUnitId)
{
this.cloudXAdUnitId = cloudXAdUnitId;
this.adMobAdUnitId = adMobAdUnitId;
CloudXAdsCallbacks.Interstitial.OnAdLoadSuccess += OnCloudXLoaded;
CloudXAdsCallbacks.Interstitial.OnAdLoadFailed += OnCloudXLoadFailed;
CloudXAdsCallbacks.Interstitial.OnAdShowSuccess += OnCloudXShown;
CloudXAdsCallbacks.Interstitial.OnAdShowFailed += OnCloudXShowFailed;
CloudXAdsCallbacks.Interstitial.OnAdHidden += OnCloudXClosed;
CloudXAdsCallbacks.Interstitial.OnAdClicked += OnCloudXClicked;
}
public void Load()
{
if (isDisposed ||
isLoadingCloudX ||
isLoadingAdMob ||
CloudXSdk.IsInterstitialReady(cloudXAdUnitId) ||
(adMobInterstitial != null && adMobInterstitial.CanShowAd()))
{
return;
}
isLoadingCloudX = true;
CloudXSdk.LoadInterstitial(cloudXAdUnitId);
}
public bool Show()
{
if (isDisposed)
{
return false;
}
if (CloudXSdk.IsInterstitialReady(cloudXAdUnitId))
{
CloudXSdk.ShowInterstitial(cloudXAdUnitId);
return true;
}
return ShowAdMobFallback();
}
public void Dispose()
{
if (isDisposed)
{
return;
}
isDisposed = true;
CloudXAdsCallbacks.Interstitial.OnAdLoadSuccess -= OnCloudXLoaded;
CloudXAdsCallbacks.Interstitial.OnAdLoadFailed -= OnCloudXLoadFailed;
CloudXAdsCallbacks.Interstitial.OnAdShowSuccess -= OnCloudXShown;
CloudXAdsCallbacks.Interstitial.OnAdShowFailed -= OnCloudXShowFailed;
CloudXAdsCallbacks.Interstitial.OnAdHidden -= OnCloudXClosed;
CloudXAdsCallbacks.Interstitial.OnAdClicked -= OnCloudXClicked;
CloudXSdk.DestroyInterstitial(cloudXAdUnitId);
DestroyAdMobInterstitial();
}
private void OnCloudXLoaded(CloudXAd ad)
{
if (ad.AdUnitId != cloudXAdUnitId)
{
return;
}
isLoadingCloudX = false;
AdLoaded?.Invoke(Source.CloudX);
}
private void OnCloudXLoadFailed(string adUnitId, CloudXError _)
{
if (adUnitId != cloudXAdUnitId)
{
return;
}
isLoadingCloudX = false;
LoadAdMobFallback();
}
private void OnCloudXShown(CloudXAd ad)
{
if (ad.AdUnitId == cloudXAdUnitId)
{
AdShown?.Invoke(Source.CloudX);
}
}
private void OnCloudXShowFailed(CloudXAd ad, CloudXError error)
{
if (ad.AdUnitId != cloudXAdUnitId)
{
return;
}
if (!ShowAdMobFallback())
{
AdShowFailed?.Invoke(Source.CloudX, error.Message);
}
}
private void OnCloudXClosed(CloudXAd ad)
{
if (ad.AdUnitId == cloudXAdUnitId)
{
AdClosed?.Invoke(Source.CloudX);
}
}
private void OnCloudXClicked(CloudXAd ad)
{
if (ad.AdUnitId == cloudXAdUnitId)
{
AdClicked?.Invoke(Source.CloudX);
}
}
private void LoadAdMobFallback()
{
if (isDisposed ||
isLoadingAdMob ||
(adMobInterstitial != null && adMobInterstitial.CanShowAd()))
{
return;
}
isLoadingAdMob = true;
DestroyAdMobInterstitial();
InterstitialAd.Load(
adMobAdUnitId,
new AdRequest(),
(ad, error) =>
{
isLoadingAdMob = false;
if (isDisposed)
{
ad?.Destroy();
return;
}
if (error != null || ad == null)
{
AdLoadFailed?.Invoke(
Source.AdMob,
error?.GetMessage() ?? "AdMob returned no ad");
return;
}
adMobInterstitial = ad;
RegisterAdMobEvents(ad);
AdLoaded?.Invoke(Source.AdMob);
});
}
private bool ShowAdMobFallback()
{
if (adMobInterstitial == null || !adMobInterstitial.CanShowAd())
{
return false;
}
adMobInterstitial.Show();
return true;
}
private void RegisterAdMobEvents(InterstitialAd ad)
{
ad.OnAdFullScreenContentOpened += () =>
AdShown?.Invoke(Source.AdMob);
ad.OnAdFullScreenContentClosed += () =>
{
DestroyAdMobInterstitial();
AdClosed?.Invoke(Source.AdMob);
};
ad.OnAdFullScreenContentFailed += error =>
{
DestroyAdMobInterstitial();
AdShowFailed?.Invoke(Source.AdMob, error.GetMessage());
};
ad.OnAdClicked += () =>
AdClicked?.Invoke(Source.AdMob);
}
private void DestroyAdMobInterstitial()
{
adMobInterstitial?.Destroy();
adMobInterstitial = null;
}
}
Show()。如果返回 false,表示 CloudX 和回退广告都没有准备好,此时应继续游戏流程,不展示广告。
if (!firstLookInterstitial.Show())
{
ContinueToNextScene();
}
Load()。拥有此控制器的 MonoBehaviour 销毁时,请调用 Dispose()。
此示例采用懒加载回退:只有 CloudX 加载失败后才加载 AdMob。除非 CloudX 针对您的游戏建议其他上线策略,否则不要并行加载两个来源。