跳转到主要内容
Trusted Arbiter 会比较已加载的 CloudX 出价与受支持的第三方出价,并返回选中的平台。从 Unity SDK 4.1.0 起可用(底层依赖 Android SDK 4.1.1 和 iOS SDK 3.4.1),支持 CloudX、Unity LevelPlay 和 PubMatic 出价输入。
请在 CloudXSdk.Initialize() 完成后(即收到 CloudXInitializationCallbacks.OnSdkInitializedEvent 事件之后)再调用 CloudXSdk.Arbiter()。在仲裁服务可用之前,SDK 会在传入的出价中回退选择可比较美元出价最高的平台。

基础 API

从已加载的广告创建出价候选项,然后传给 CloudXSdk.Arbiter()
using System.Collections.Generic;
using CloudX;
using UnityEngine;

// cloudXAd 是 CloudX OnAdLoadSuccess 回调中的 CloudXAd 对象。
// 它的 AdValues 映射携带了服务器用于校验出价的受信任载荷键。
// levelPlayNetwork / levelPlayRevenue / levelPlayPrecision 来自 Unity LevelPlay 广告信息。
// pubMaticPrice 和 pubMaticPartner 来自 PubMatic/OpenWrap 出价对象。
var bids = new List<CloudXArbiterBid>
{
    new CloudXArbiterBid.CloudX(cloudXAd),
    new CloudXArbiterBid.LevelPlay(
        NetworkName: levelPlayNetwork,
        Revenue: levelPlayRevenue,
        Precision: levelPlayPrecision),
    new CloudXArbiterBid.PubMatic(
        Price: pubMaticPrice,
        PartnerName: pubMaticPartner),
};

CloudXSdk.Arbiter(bids, result =>
{
    Debug.Log($"选中的平台: {result.Platform}");
});
CloudXArbiterBid.CloudX 接收 CloudX 加载回调中的 CloudXAd 对象。CloudXArbiterBid.LevelPlay 接收 Unity LevelPlay 广告信息值。CloudXArbiterBid.PubMatic 接收 PubMatic OpenWrap 出价价格和可选的合作伙伴名称。Extras 映射在 LevelPlayPubMatic 出价中均为可选参数,PartnerNamePubMatic 出价中为可选参数。完成回调在主线程上执行,因此你可以直接在其中展示广告或更新 UI。 result.Platform 在选中平台时为 CloudXArbiterPlatform.CloudXLevelPlayPubMatic;当无法选出获胜平台时(例如未传入任何出价),则为 CloudXArbiterPlatform.None。结果还提供 result.Id(拍卖标识符)、result.BidId(获胜出价标识符,当平台为 None 时为 null)以及 result.Extras(获胜广告网络返回的附加元数据)。

分步示例:在 CloudX 与 LevelPlay 之间仲裁

本演练展示了应读取哪个 Unity LevelPlay 回调,以及应将哪些值传入 CloudXSdk.Arbiter()。示例使用插屏广告,但相同的字段映射适用于任何广告格式。
1

加载两个候选项

创建 LevelPlay 插屏广告,并为每个平台启动加载。请在加载之前订阅加载回调。
var levelPlayAd = new LevelPlayInterstitialAd("YOUR_LEVELPLAY_AD_UNIT_ID");
levelPlayAd.OnAdLoaded += OnLevelPlayLoaded;
levelPlayAd.OnAdLoadFailed += OnLevelPlayLoadFailed;
levelPlayAd.LoadAd();

CloudXAdsCallbacks.Interstitial.OnAdLoadSuccess += OnCloudXLoaded;
CloudXSdk.LoadInterstitial("YOUR_CLOUDX_AD_UNIT_ID");
2

保存每个平台已加载的广告

LevelPlay 在其 OnAdLoaded 回调中提供 LevelPlayAdInfo;CloudX 在 OnAdLoadSuccess 中提供 CloudXAd。请保存两者——下一步会从中读取仲裁输入。
private CloudXAd _cloudXAd;
private LevelPlayAdInfo _levelPlayInfo;

private void OnCloudXLoaded(CloudXAd ad) => _cloudXAd = ad;
private void OnLevelPlayLoaded(LevelPlayAdInfo info) => _levelPlayInfo = info;
3

将值映射为出价

LevelPlayAdInfo 读取 LevelPlay 字段,并传给 CloudXArbiterBid.LevelPlay。CloudX 出价直接接收 CloudXAd
LevelPlayAdInfo 字段类型CloudXArbiterBid.LevelPlay 参数
adNetworkstringNetworkName
revenuedouble?Revenue(用 ?? 0 合并空值)
precisionstringPrecision
var bids = new List<CloudXArbiterBid>
{
    new CloudXArbiterBid.CloudX(_cloudXAd),
    new CloudXArbiterBid.LevelPlay(
        NetworkName: _levelPlayInfo.adNetwork,   // LevelPlayAdInfo.adNetwork
        Revenue: _levelPlayInfo.revenue ?? 0,    // LevelPlayAdInfo.revenue 为 double?
        Precision: _levelPlayInfo.precision),    // LevelPlayAdInfo.precision
};
4

运行仲裁器

将出价连同完成回调传给 CloudXSdk.Arbiter()。回调在 Unity 主线程上执行。
CloudXSdk.Arbiter(bids, OnArbiterCompleted);
5

展示获胜平台

根据 result.Platform 进行分支,展示获胜平台的广告。CloudXArbiterPlatform.None 表示未选出获胜平台——此时不展示广告,继续应用流程。
private void OnArbiterCompleted(CloudXArbiterResult result)
{
    switch (result.Platform)
    {
        case CloudXArbiterPlatform.CloudX:
            CloudXSdk.ShowInterstitial("YOUR_CLOUDX_AD_UNIT_ID", "level_complete");
            break;
        case CloudXArbiterPlatform.LevelPlay:
            levelPlayAd.ShowAd("level_complete");
            break;
        default:
            break; // CloudXArbiterPlatform.None——无获胜平台;不展示广告
    }
}
在 LevelPlay Unity SDK 8.x 中,LevelPlayAdInfo 使用 camelCase 字段(adNetworkrevenueprecision)。revenuedouble?,因此在传给非空的 Revenue 参数时请使用 ?? 0 合并空值。
下方的 ArbiterInterstitialController 将上述步骤封装为一个可复用的组件,会在到达广告位之前提前准备好获胜平台。

插屏广告示例

这个插屏广告示例会在两个平台之间仲裁:CloudX 和 Unity LevelPlay。在到达广告位之前先准备好获胜平台:
  1. 并行加载 CloudX 和 LevelPlay。
  2. 等待两个平台都加载完成或加载失败。
  3. 只将已加载的候选项提交给 Trusted Arbiter。
  4. 缓存选中的平台。
  5. 到达广告位时,立即展示缓存的获胜广告。
如果两个平台都加载失败,开始新的加载周期。如果到达广告位时还没有准备好获胜平台,则继续应用流程,不展示广告。
ArbiterInterstitialController.cs
using System.Collections.Generic;
using CloudX;
using UnityEngine;

/// <summary>
/// 提前准备好 Trusted Arbiter 的获胜平台,以便在到达广告位时立即展示插屏广告。
///
/// 并行加载 CloudX 和 LevelPlay 插屏广告,等待两者都加载完成或加载失败,
/// 将已加载的候选项提交给 CloudXSdk.Arbiter,并将选中的 CloudXArbiterPlatform
/// 缓存到 _nextWinner 中。
/// </summary>
public class ArbiterInterstitialController : MonoBehaviour
{
    private const string CloudXAdUnitId = "interstitial_main";

    // 当 LevelPlay Unity SDK 报告插屏广告已加载时,由宿主设置。
    public string LevelPlayNetwork;
    public double LevelPlayRevenue;
    public string LevelPlayPrecision;

    // 当仲裁器为下一次展示选出平台后调用。
    public System.Action<CloudXArbiterPlatform> OnWinnerPrepared;

    private CloudXAd _cloudXAd;
    private bool _cloudXLoadDone;
    private bool _levelPlayLoaded;
    private bool _levelPlayLoadDone;
    private CloudXArbiterPlatform? _nextWinner;

    private void OnEnable()
    {
        CloudXAdsCallbacks.Interstitial.OnAdLoadSuccess += OnCloudXLoaded;
        CloudXAdsCallbacks.Interstitial.OnAdLoadFailed += OnCloudXLoadFailed;
        CloudXAdsCallbacks.Interstitial.OnAdHidden += OnCloudXHidden;
        CloudXAdsCallbacks.Interstitial.OnAdShowFailed += OnCloudXShowFailed;
    }

    private void OnDisable()
    {
        CloudXAdsCallbacks.Interstitial.OnAdLoadSuccess -= OnCloudXLoaded;
        CloudXAdsCallbacks.Interstitial.OnAdLoadFailed -= OnCloudXLoadFailed;
        CloudXAdsCallbacks.Interstitial.OnAdHidden -= OnCloudXHidden;
        CloudXAdsCallbacks.Interstitial.OnAdShowFailed -= OnCloudXShowFailed;
    }

    /// <summary>为每个当前没有缓存广告的平台启动加载。</summary>
    public void LoadMissingAds()
    {
        if (_cloudXAd == null) CloudXSdk.LoadInterstitial(CloudXAdUnitId);
        if (!_levelPlayLoaded) LoadLevelPlayInterstitial();
    }

    /// <summary>
    /// 展示已准备好的获胜广告,仅当确实发起了展示调用时返回 true。
    ///
    /// 当没有准备好获胜平台或缓存的广告已不可用时返回 false,
    /// 此时会启动一次新的加载周期。
    /// </summary>
    public bool ShowAtPlacement(string placement)
    {
        switch (_nextWinner)
        {
            case CloudXArbiterPlatform.CloudX:
                return ShowCloudX(placement);
            case CloudXArbiterPlatform.LevelPlay:
                return ShowLevelPlay(placement);
            default:
                return false;
        }
    }

    /// <summary>
    /// 在两个平台都完成后运行仲裁器,然后缓存获胜平台。
    ///
    /// 在两个加载都完成之前提前返回。如果两个平台都没有加载成功,则重启加载周期;
    /// 否则将已加载的候选项提交给 CloudXSdk.Arbiter。
    /// </summary>
    private void MaybePrepareWinner()
    {
        if (!_cloudXLoadDone || !_levelPlayLoadDone) return;

        if (_cloudXAd == null && !_levelPlayLoaded)
        {
            _cloudXLoadDone = false;
            _levelPlayLoadDone = false;
            LoadMissingAds();
            return;
        }

        var bids = new List<CloudXArbiterBid>();
        if (_cloudXAd != null)
        {
            bids.Add(new CloudXArbiterBid.CloudX(_cloudXAd));
        }

        if (_levelPlayLoaded)
        {
            bids.Add(new CloudXArbiterBid.LevelPlay(
                NetworkName: LevelPlayNetwork,
                Revenue: LevelPlayRevenue,
                Precision: LevelPlayPrecision));
        }

        CloudXSdk.Arbiter(bids, result =>
        {
            _nextWinner = result.Platform;
            OnWinnerPrepared?.Invoke(result.Platform);
        });
    }

    private bool ShowCloudX(string placement)
    {
        if (CloudXSdk.IsInterstitialReady(CloudXAdUnitId))
        {
            CloudXSdk.ShowInterstitial(CloudXAdUnitId, placement);
            return true;
        }

        ClearCloudXAndLoadMissingAds();
        return false;
    }

    private bool ShowLevelPlay(string placement)
    {
        if (IsLevelPlayInterstitialReady())
        {
            ShowLevelPlayInterstitial(placement);
            return true;
        }

        ClearLevelPlayAndLoadMissingAds();
        return false;
    }

    private void OnCloudXLoaded(CloudXAd ad)
    {
        _cloudXAd = ad;
        _cloudXLoadDone = true;
        MaybePrepareWinner();
    }

    private void OnCloudXLoadFailed(string adUnitId, CloudXError error)
    {
        _cloudXAd = null;
        _cloudXLoadDone = true;
        MaybePrepareWinner();
    }

    private void OnCloudXHidden(CloudXAd ad) => ClearCloudXAndLoadMissingAds();

    private void OnCloudXShowFailed(CloudXAd ad, CloudXError error) => ClearCloudXAndLoadMissingAds();

    private void ClearCloudXAndLoadMissingAds()
    {
        _cloudXAd = null;
        _cloudXLoadDone = false;
        _nextWinner = null;
        LoadMissingAds();
    }

    private void ClearLevelPlayAndLoadMissingAds()
    {
        _levelPlayLoaded = false;
        _levelPlayLoadDone = false;
        _nextWinner = null;
        LoadMissingAds();
    }

    /*
     * 下面的成员封装了 LevelPlay Unity SDK。请用你集成的 LevelPlay SDK 调用替换其方法体,
     * 并将其加载回调接入上面的字段:加载成功时,设置 _levelPlayLoaded = true 及各个
     * LevelPlay* 值,然后设置 _levelPlayLoadDone = true 并调用 MaybePrepareWinner();
     * 加载失败时,设置 _levelPlayLoaded = false、_levelPlayLoadDone = true,
     * 并调用 MaybePrepareWinner()。广告关闭或展示失败时,调用
     * ClearLevelPlayAndLoadMissingAds() 以丢弃已消耗的广告并开始新的加载周期。
     */
    private void LoadLevelPlayInterstitial() { /* LevelPlay.LoadInterstitial(...) */ }
    private bool IsLevelPlayInterstitialReady() => _levelPlayLoaded;
    private void ShowLevelPlayInterstitial(string placement) { /* LevelPlay.ShowInterstitial(...) */ }
}
ShowAtPlacement() 仅当确实发起了展示调用时返回 true。在 LevelPlay 广告保持加载状态期间,请持续更新缓存的 LevelPlay 候选项值。 对于 PubMatic OpenWrap,使用 new CloudXArbiterBid.PubMatic(price, partnerName) 创建第三方出价。如果仲裁服务不可用,SDK 会在传入的受支持出价输入中回退选择可比较美元出价最高的平台。