返回顶部

海外SDK集成文档(Unity版本)

注意,文档内容包括广告、统计业务,如果有内购需求请参考Android版本文档IOS版本文档

发布前务必检查以下事项

  • Android端minSdkVersion必须大于等于19,targetSdkVersion必须大于等于29;
  • Android端manifest文件务必去除所有敏感权限声明(READ_PHONE_STATE、WRITE_EXTENAL_STORAGE等);

1. 广告接入

广告部分需要接入AdMob聚合平台。

广告接入必接步骤大致如下:

 1)集成admob sdk;
 2)集成admob第三方广告平台网络适配器sdk,此sdk是admob为了适配聚合第三方广告的插件sdk;
 3)集成第三方广告网络sdk,admob是一个聚合广告平台,它下面有多个第三方广告网络;
 4)初始化并集成广告格式代码;
 5)测试验证。

1.1 添加SDK依赖

导入SDK前需具备以下开发环境:

  • 使用 Unity 5.6 或更高版本;
  • 要在 iOS 上打包,需具备Xcode12和Cocoapods;
  • 要在 Android 上打包,则需要Android API 级别 14 或更高级别为目标平台;

1.1.1 导入AdMob Unity插件

导入步骤:

1)下载最新的AdMob Unity插件,下载地址

2)在Unity顶部菜单栏中选择Assets-->Import Package-->Custom Package,选择下载好的AdMob Unity插件,选择所有文件,点击Import。

3)导入原生SDK,如下所示:

Android

在 Unity 编辑器中,依次选择 Assets > External Dependency Manager > Android Resolver > Resolve。Unity 外部依赖项管理器库会将声明的依赖项复制到 Unity 应用的 Assets/Plugins/Android 目录中。

iOS

无需其他操作,使用 Unity 5.6 及更高版本时,系统会生成包含所需依赖项库的 xcworkspace。请使用生成的 xcworkspace打开工程,而不要使用标准 Xcode 项目;

1.1.2 设置AdMob AppId

在 Unity 编辑器中,从菜单中依次选择 Assets > Google Mobile Ads > Settings,在Inspector面板中填入Appid并勾选Google AdMob的Enabled复选框。

1.1.3 添加第三方广告网络SDK和适配器

打开以下链接,导航栏中选择“Files”下载最新版本以下平台的unity包导入工程:

1.2 接口调用

调用Admob接口前需要先导入命名空间:

 using GoogleMobileAds.Api;
 using GoogleMobileAds.Common;

1.2.1 初始化

在第一个场景的Start()方法中调用初始化接口:

   public void Start()
    {
        // 初始化admob.
        MobileAds.Initialize((initStatus) =>
        {   
            //以下代码用于打印第三方平台SDK适配器准备状态
            Dictionary<string, AdapterStatus> map = initStatus.getAdapterStatusMap();
            foreach (KeyValuePair<string, AdapterStatus> keyValuePair in map)
            {
                string className = keyValuePair.Key;
                AdapterStatus status = keyValuePair.Value;
                switch (status.InitializationState)
                {
                case AdapterState.NotReady:
                    // The adapter initialization did not complete.
                    MonoBehaviour.print("Adapter: " + className + " not ready.");
                    break;
                case AdapterState.Ready:
                    // The adapter was successfully initialized.
                    MonoBehaviour.print("Adapter: " + className + " is initialized.");
                    break;
                }
            }

            //如果有预加载广告,必须要初始化结束之后请求广告

        });
        ...
    }

1.2.2 激励视频广告

激励视频广告第一次加载建议在初始化完成后立即加载,在需要展示广告的时候手动展示,广告关闭后可以缓存下一个广告,以便下一次能顺利展示。

创建实例

  • 注意激励视频实例不能复用,每次请求广告必须重新创建实例;

  • 通过adUnitId创建激励视频实例,adUnitId由我方运营提供,请在运营提供的参数文档中获取。

RewardedAd rewardedAd = new RewardedAd(adUnitId);

广告价值回传方法

 this.rewardedAd.OnPaidEvent += this.HandleAdPaidEvent;

public void HandleAdPaidEvent(object sender, AdValueEventArgs args) { 
    AdValue adValue = args.AdValue; 
    Firebase.Analytics.Parameter[] LTVParameters = { 
        new Firebase.Analytics.Parameter("valuemicros", adValue.value), 
        new Firebase.Analytics.Parameter("currency", adValue.CurrencyCode), 
        new Firebase.Analytics.Parameter("precision", adValue.Precision), 
        new Firebase.Analytics.Parameter("adunitid", <your-ad-unit-id>), 
        new Firebase.Analytics.Parameter("network", this.rewardedAd.MediationAdapterClassName()) 
    };
    Firebase.Analytics.FirebaseAnalytics.LogEvent("ad_revenue", LTVParameters); 

}

添加广告事件回调方法

// 广告加载成功时回调
rewardedAd.OnAdLoaded += HandleRewardedAdLoaded;
// 广告加载失败时回调
rewardedAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;
// 广告展示成功时回调
rewardedAd.OnAdOpening += HandleRewardedAdOpening;
// 广告展示失败时回调
rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// 奖励回调
rewardedAd.OnUserEarnedReward += HandleUserEarnedReward;
// 广告关闭时回调,在这里可以进行缓存下一个广告
rewardedAd.OnAdClosed += HandleRewardedAdClosed;

public void HandleRewardedAdLoaded(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleRewardedAdLoaded event received");
}

public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
{
    MonoBehaviour.print(
        "HandleRewardedAdFailedToLoad event received with message: "
        + args.Message);
}

public void HandleRewardedAdOpening(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleRewardedAdOpening event received");
}

public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
    MonoBehaviour.print(
        "HandleRewardedAdFailedToShow event received with message: "
        + args.Message);
}

public void HandleRewardedAdClosed(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleRewardedAdClosed event received");
}

public void HandleUserEarnedReward(object sender, Reward args)
{
    string type = args.Type;
    double amount = args.Amount;
    MonoBehaviour.print(
        "HandleRewardedAdRewarded event received for "
        + amount.ToString() + " " + type);
}

加载广告

 AdRequest request = new AdRequest.Builder().Build();
 //请求广告打点可以在这里设置
 rewardedAd.LoadAd(request);

展示广告

 if (rewardedAd.IsLoaded()) {
    rewardedAd.Show();
 }

1.2.3 插屏广告

创建插屏广告实例

  • 注意插屏实例不能复用,每次请求广告必须重新创建实例;
  • 通过adUnitId创建插屏实例,adUnitId由我方运营提供,请在运营提供的参数文档中获取。
 using GoogleMobileAds.Api;
...

private InterstitialAd interstitial;

private void RequestInterstitial()
{
    #if UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/1033173712";
    #elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/4411468910";
    #else
        string adUnitId = "unexpected_platform";
    #endif

    // Initialize an InterstitialAd.
    this.interstitial = new InterstitialAd(adUnitId);
}

广告价值回传方法

 this.interstitial.OnPaidEvent += this.HandleAdPaidEvent;

public void HandleAdPaidEvent(object sender, AdValueEventArgs args) { 
    AdValue adValue = args.AdValue; 
    Firebase.Analytics.Parameter[] LTVParameters = { 
        new Firebase.Analytics.Parameter("valuemicros", adValue.value), 
        new Firebase.Analytics.Parameter("currency", adValue.CurrencyCode), 
        new Firebase.Analytics.Parameter("precision", adValue.Precision), 
        new Firebase.Analytics.Parameter("adunitid", <your-ad-unit-id>), 
        new Firebase.Analytics.Parameter("network", this.interstitial.MediationAdapterClassName()) 
    };
    Firebase.Analytics.FirebaseAnalytics.LogEvent("ad_revenue", LTVParameters); 

}

添加事件回调方法

请求广告前需要添加以下回调方法:

     // 广告加载成功
    this.interstitial.OnAdLoaded += HandleOnAdLoaded;
    // 广告加载失败
    this.interstitial.OnAdFailedToLoad += HandleOnAdFailedToLoad;
    // 广告展示成功
    this.interstitial.OnAdOpening += HandleOnAdOpened;
    //广告关闭
    this.interstitial.OnAdClosed += HandleOnAdClosed;



public void HandleOnAdLoaded(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleAdLoaded event received");
}

public void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
    MonoBehaviour.print("HandleFailedToReceiveAd event received with message: "
                        + args.Message);
}

public void HandleOnAdOpened(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleAdOpened event received");
}

public void HandleOnAdClosed(object sender, EventArgs args)
{
    MonoBehaviour.print("HandleAdClosed event received");
}

加载广告

    // Create an empty ad request.
    AdRequest request = new AdRequest.Builder().Build();
    // Load the interstitial with the request.
    this.interstitial.LoadAd(request);

展示广告

 if (this.interstitial.IsLoaded()) {
    this.interstitial.Show();
 }

1.2.4 横幅(Banner)广告

创建实例

BannerView 的构造函数包含以下参数:

  • adUnitId - AdMob 广告单元 ID,联系我方运营进行获取。
  • AdSize - 要使用的 AdMob 广告尺寸(有关详情,请参阅横幅广告尺寸)。
  • AdPosition - 应放置横幅广告的位置。AdPosition 枚举列出了有效的广告位置值。
using System;
using UnityEngine;
using GoogleMobileAds.Api;
...
public class GoogleMobileAdsDemoScript : MonoBehaviour
{
    private BannerView bannerView;
    ...
    public void Start()
    {
        // Initialize the Google Mobile Ads SDK.
        MobileAds.Initialize(initStatus => { });

        this.RequestBanner();
    }

    private void RequestBanner()
    {
        #if UNITY_ANDROID
            string adUnitId = "ca-app-pub-3940256099942544/6300978111";
        #elif UNITY_IPHONE
            string adUnitId = "ca-app-pub-3940256099942544/2934735716";
        #else
            string adUnitId = "unexpected_platform";
        #endif

        // Create a 320x50 banner at the top of the screen.
        this.bannerView = new BannerView(adUnitId, AdSize.Banner, AdPosition.Top);
    }
}

(可选)自定义广告位置

为了更好地控制 BannerView 在屏幕上的位置(而不是 AdPosition 值提供的位置),请使用带有 x 坐标和 y 坐标参数的 BannerView 构造函数。

// Create a 320x50 banner ad at coordinate (0,50) on screen.
BannerView bannerView = new BannerView(adUnitId, AdSize.Banner, 0, 50);

BannerView 的左上角将放置在传给构造函数的 x 值和 y 值所确定的位置,原点则是屏幕的左上角。

(可选)自定义广告尺寸

除了使用 AdSize 常量之外,您还可以为广告指定自定义尺寸:

AdSize adSize = new AdSize(250, 250);
BannerView bannerView = new BannerView(adUnitId, adSize, AdPosition.Bottom);

广告价值回传方法

 this.bannerView.OnPaidEvent += this.HandleAdPaidEvent;

public void HandleAdPaidEvent(object sender, AdValueEventArgs args) { 
    AdValue adValue = args.AdValue; 
    Firebase.Analytics.Parameter[] LTVParameters = { 
        new Firebase.Analytics.Parameter("valuemicros", adValue.value), 
        new Firebase.Analytics.Parameter("currency", adValue.CurrencyCode), 
        new Firebase.Analytics.Parameter("precision", adValue.Precision), 
        new Firebase.Analytics.Parameter("adunitid", <your-ad-unit-id>), 
        new Firebase.Analytics.Parameter("network", this.bannerView.MediationAdapterClassName()) 
    };
    Firebase.Analytics.FirebaseAnalytics.LogEvent("ad_revenue", LTVParameters); 

}

添加广告回调事件方法

  // banner加载成功
  this.bannerView.OnAdLoaded += this.HandleOnAdLoaded;
  // banner加载失败
  this.bannerView.OnAdFailedToLoad += this.HandleOnAdFailedToLoad;
  // 展示成功
  this.bannerView.OnAdOpening += this.HandleOnAdOpened;
  //广告关闭
  this.bannerView.OnAdClosed += this.HandleOnAdClosed;


    public void HandleOnAdLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdLoaded event received");
    }

    public void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
    {
        MonoBehaviour.print("HandleFailedToReceiveAd event received with message: "
                            + args.Message);
    }

    public void HandleOnAdOpened(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdOpened event received");
    }

    public void HandleOnAdClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdClosed event received");
    }

    public void HandleOnAdLeavingApplication(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdLeavingApplication event received");
    }

加载并展示广告

 // Create an empty ad request.
 AdRequest request = new AdRequest.Builder().Build();
 // Load the banner with the request.
 this.bannerView.LoadAd(request);

销毁banner

 bannerView.Destroy();

1.3 测试与验证

测试前设备需要开启VPN(建议美国地区),否则可能会有加载不到广告的现象。

注意!对于激励视频和插屏广告强烈不建议在广告加载失败回调中进行加载广告,如果一定要这么做,务必限制重新加载次数,避免造成死循环。

激励视频和插屏广告建议在以下时机进行请求广告:

  1. 首次请求在游戏启动广告SDK初始化成功时;

  2. 缓存下一个广告在广告关闭的回调里进行加载;

  3. 在展示广告前的某个时机应该提前判断是否有广告,没有广告就去进行加载广告。

对于第三点,比如关卡结束时有广告埋点,游戏应该在关卡开始时先判断有没有广告已经填充,如果没有就要去进行加载广告。

1.3.1使用测试广告单元Id测试,确保AdMob集成无误

Android

横幅广告    ca-app-pub-3940256099942544/6300978111
插页式广告   ca-app-pub-3940256099942544/1033173712
激励视频广告  ca-app-pub-3940256099942544/5224354917
原生高级广告  ca-app-pub-3940256099942544/2247696110

iOS

横幅广告    ca-app-pub-3940256099942544/2934735716
插页式广告   ca-app-pub-3940256099942544/4411468910
激励视频广告  ca-app-pub-3940256099942544/1712485313
原生高级广告  ca-app-pub-3940256099942544/3986624511

1.3.2 测试中介联盟广告,确保第三方广告集成无误

添加测试设备

以下添加方式选择一种即可

  • AdMob后台添加,联系我方运营进行添加;
  • 代码中添加,如下步骤所示:
1)运行游戏,发起一个广告请求;
2)检查控制台或者logcat的日志,查找以下内容:
   Android:
     I/Ads: Use
      RequestConfiguration.Builder
        .setTestDeviceIds(Arrays.asList("33BE2250B43518CCDA7DE426D04EE231"))
      to get test ads on this device.

   iOS:
      <Google> To get test ads on this device, set:
      GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers =
      @[ @"2077ef9a63d2b398840261c8221a0c9b" ];

3)复制日志中的设备id;
4)代码中设置测试设备:
//可以在初始化前添加
List<string> deviceIds = new List<string>();
deviceIds.Add("2077ef9a63d2b398840261c8221a0c9b");
RequestConfiguration requestConfiguration = new RequestConfiguration
    .Builder()
    .SetTestDeviceIds(deviceIds)
    .build();
MobileAds.SetRequestConfiguration(requestConfiguration);

下载中介测试套件并导入

下载地址

在Unity顶部菜单栏中选择Assets-->Import Package-->Custom Package,选择下载好的测试套件包,选择所有文件,点击Import。

展示测试套件

在admob初始化完成时调用一下代码开启测试套件:

using GoogleMobileAdsMediationTestSuite.Api;

private void ShowMediationTestSuite()
{
    MediationTestSuite.Show();
}

注意!正式发布时,需要把测试套件代码注释!

在设备上运行游戏

运行游戏,启动时会弹出测试套件界面,逐一对每个平台进行加载、展示广告即可。

2. 统计接入

统计需要接入以下两个平台。

Adjust用于归因事件统计与转发,不同用户来源追踪、质量追踪等;

Firebase用于归因与事件整合分析,用户行为分析。

2.1 Adjust

2.1.1 添加SDK依赖

获取SDK

下载最新版本的SDK:下载地址

添加SDK到项目

在菜单栏中选择Assets-->Import Package-->Custom Package,选择下载好的Unity package文件,点击Import。

添加Google Install Referrer

为了将安卓应用的安装正确归因到其来源,Adjust需要关于install referrer的信息。这里只需下载好install referrer库,并将aar文件复制到Assets/Plugins/Android目录下即可。

2.1.2 初始化Adjust(必接)

将位于Assets/Adjust.prefab的prefab(预制件)添加到第一场景。

单击Adjust预制件,属性面板里可以设置以下内容:

  • 手动启动(Start Manually)
  • 事件缓冲(Event Buffer)
  • 后台发送(Send In Background)
  • 打开延迟深度链接(Launch Deferred Deeplink)
  • 应用Token(APP Token)
  • 日志等级(Log Level)
  • 环境模式(Environment) 正式环境用Production,测试环境用Sandbox。

开发者这里暂时只需关心手动启动、应用Token、日志等级、环境模式。如果不希望Adjust在Awake事件中自动启动初始化,要勾选手动启动,那么就要手动在代码里初始化Adjust SDK,初始化示例代码如下:

 string appToken = "{YourAppToken}";
 string environment = AdjustEnvironment.Sandbox;

 AdjustConfig config = new AdjustConfig(appToken, environment, true);
 config.setLogLevel(AdjustLogLevel.Suppress);
 config.setAttributionChangedDelegate(this.attributionChangedDelegate);

 Adjust.start(config);
 //归因回传,用于Firebase adjust_conversion事件
 public void attributionChangedDelegate(AdjustAttribution attribution) {
        Debug.Log("Attribution changed");
        String network = attribution.network;
        String campaign  = attribution.campaign;
        String adgroup = attribution.adgroup;
        String creative  = attribution.creative;
        //Firebase埋点,必须添加
       Firebase.Analytics.Parameter[] testParameters = {
          new Firebase.Analytics.Parameter(
            "network", network),
          new Firebase.Analytics.Parameter(
            "campaign", campaign),
          new Firebase.Analytics.Parameter(
            "adgroup", adgroup)
          new Firebase.Analytics.Parameter(
            "creative", creative)
        };
        Firebase.Analytics.FirebaseAnalytics.LogEvent(
          "adjust_conversion",
          testParameters);
         }

如果没有勾选手动启动,那么就要在属性面板里配置好应用Token、日志等级、环境模式,然后保存,这样SDK就会在Awake事件中自动启动SDK,无需再在代码中进行初始化。

检测Google Play服务

对于Google Play商店的应用Adjust必须使用Google广告ID来唯一识别设备,所以开发者必须集成Google Play服务,必须添加play-services-ads-identifier,PlayServicesResolver解析时会将这个依赖自动添加。

务必测试Adjust SDK是否成功获取了Google广告标识符,测试步骤:

1)初始化时把环境模式设置为Sandbox(测试完毕发布产品时要设置为Production);

2)将日志级别设置为verbose;

3)运行项目,观察在verbose日志中读取的参数列表。

4)如果看到名为gps_adid的参数,那么说明Adjust SDK已经获取到了Google广告标识符。

2.1.3 事件打点

事件打点前要引入Adjust命名空间,代码如下:

 using com.adjust.sdk;

Adjust事件跟踪

在应用中需要跟踪的地方添加如下代码:

 AdjustEvent adjustEvent = new AdjustEvent("abc123");
 Adjust.trackEvent(adjustEvent);

abc123为你的事件token,需要打点的话必须先在后台创建事件获取这个token。

2.2 Firebase

2.2.1 添加配置文件

运营人员会提供好配置文件,将这个配置文件添加到相应的目录下即可。

Android

google-services.json文件添加到项目的Assets目录下。

iOS

GoogleService-Info.plist文件添加到项目的Assets目录下。

2.2.2 添加SDK依赖包

下载SDK

下载地址

下载的压缩文件是Firebase所有组件的SDK约有1GB的大小,我们目前只需Analytics模块,如果因为网络问题下载较慢,可以联系运营人员直接提供FirebaseAnalytics.unitypackage。

导入SDK到Unity

在菜单栏中选择Assets > Import Package > Custom Package,选择下载好的SDK中FirebaseAnalytics.unitypackage包,其他包暂时不用导入。

2.2.3 检测谷歌服务版本

Android 版 Firebase Unity SDK 需要使用 Google Play 服务。必须先将 Google Play 服务更新为最新版本,然后才能使用该 SDK。

应在应用开头处添加以下代码,以便检查 Google Play 服务版本是否符合 Firebase Unity SDK 的要求,并视情况将其更新为相应版本,然后再调用 SDK 中的任何其他方法。

 Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
  var dependencyStatus = task.Result;
  if (dependencyStatus == Firebase.DependencyStatus.Available) {
    // Create and hold a reference to your FirebaseApp,
    // where app is a Firebase.FirebaseApp property of your application class.
    //   app = Firebase.FirebaseApp.DefaultInstance;

    // Set a flag here to indicate whether Firebase is ready to use by your app.
  } else {
    UnityEngine.Debug.LogError(System.String.Format(
      "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
    // Firebase Unity SDK is not safe to use here.
  }
 });

2.2.4 设置Firebase奔溃报告SDK

1)将下载好的SDK里FirebaseCrashlytics.unitypackage导入到Unity;

2)在你的第一个场景创建一个名为CrashlyticsInitializer的空GameObject;

3)在CrashlyticsInitializer的Inspector面板中点击Add Component,选择CrashlyticsInit脚本将其添加进去;

4)在第一个场景的脚本start()方法中进行初始化:

  void Start () {
          // Initialize Firebase
          Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
              var dependencyStatus = task.Result;
              if (dependencyStatus == Firebase.DependencyStatus.Available)
              {
                  // Create and hold a reference to your FirebaseApp,
                  // where app is a Firebase.FirebaseApp property of your application class.
                  // Crashlytics will use the DefaultInstance, as well;
                  // this ensures that Crashlytics is initialized.
                  Firebase.FirebaseApp app = Firebase.FirebaseApp.DefaultInstance;

                  // Set a flag here for indicating that your project is ready to use Firebase.
              }
              else
              {
                  UnityEngine.Debug.LogError(System.String.Format(
                    "Could not resolve all Firebase dependencies: {0}",dependencyStatus));
                  // Firebase Unity SDK is not safe to use here.
              }
          });
      }

5)打包到双端运行游戏。

2.2.5 自定义事件

Firebase统计以事件为核心进行用户行为的分析,每个事件下面可以附带不同的参数进行上传。

事件不带参数

 //参数传事件名称
 Firebase.Analytics.FirebaseAnalytics
  .LogEvent("level_enter");

事件带一个参数

 //第一个参数事件名称,第二个参数是事件的参数名称,第三个参数是事件参数的参数值
 Firebase.Analytics.FirebaseAnalytics
  .LogEvent("progress", "percent", 0.4f);//浮点型

 Firebase.Analytics.FirebaseAnalytics
  .LogEvent("level_enter", "level_useTime", 26);//整型

 Firebase.Analytics.FirebaseAnalytics
  .LogEvent("ads_RV_show", "location", "level_win_1");//字符串

事件带多个参数

 Firebase.Analytics.Parameter[] testParameters = {
  new Firebase.Analytics.Parameter(
    "level_useTime", 5),
  new Firebase.Analytics.Parameter(
    "location", "level_win_1"),
  new Firebase.Analytics.Parameter(
    "percent", 3.14f)
};//构建参数数组
Firebase.Analytics.FirebaseAnalytics.LogEvent(
  "test_event",
  testParameters);//将参数数组传入事件

具体要统计的事件和规范请参考这里

2.2.6 记录用户属性

用户属性用于记录用户长期不变或者变化缓慢的属性,可以将用户进行动态分群,后台可以直接将这个属性作为过滤条件,每次事件的上报都会附带用户属性一起上报。

以下示例中表示用户来源于Facebook平台:

 //第一个参数是用户属性名称,第二个参数是属性值
 Firebase.Analytics.FirebaseAnalytics.SetUserProperty("source_network", "facebook");

2.2.7 测试验证

由于Firebase后台数据有很长时间的延迟(24小时左右),测试数据没办法在后台马上能看到,要看实时测试数据需要用到Firebase后台的DebugView。请按以下步骤进行测试:

Android

 1)将设备打开USB调试连接电脑,注意设备和电脑都要翻墙;
 2)在设备上安装好游戏apk,注意此时不要启动游戏;
 3)打开Firebase后台DebugView;
 4)打开cmd终端输入以下命令(例如包名是com.yunbu.apptest,实际测试替换为游戏包名):
    adb shell setprop debug.firebase.analytics.app com.yunbu.apptest
 5)启动游戏,稍等十几秒DebugView左上角会出现你的设备名称,主面板会依次出现你打的事件名称。

iOS

 1)将设备打开USB调试连接电脑,注意设备和电脑都要翻墙;
 2)打开Firebase后台DebugView;
 3)在Xcode Product> Scheme> Edit scheme>Arguments> Launch > Add items,输入以下命令:
    -FIRDebugEnabled
 4)在Xcode上运行游戏,运行成功后稍等十几秒DebugView左上角会出现你的设备名称,主面板会依次出现你打的事件名称。

2.2.8 Firebase远程配置接入(可选)

远程配置用于动态参数调整,可以根据后台配置的参数,来在客户端做出不同的行为调整。

导入SDK包

在2.2.2中下载好的SDK里获取FirebaseRemoteConfig.unitypackage包导入到Unity。

接口调用

设置默认参数

如果出现获取不到后台设置的参数值,可以获取本地存储的默认值:

    System.Collections.Generic.Dictionary<string, object> defaults =
      new System.Collections.Generic.Dictionary<string, object>();

    // These are the values that are used if we haven't fetched data from the
    // server
    // yet, or if we ask for values that the server doesn't have:
    defaults.Add("config_test_string", "default local string");
    defaults.Add("config_test_int", 1);
    defaults.Add("config_test_float", 1.0);
    defaults.Add("config_test_bool", false);

    Firebase.RemoteConfig.FirebaseRemoteConfig.SetDefaults(defaults);

获取后台参数配置

通过调用FetchAsync()方法可以向服务器请求参数配置,请求成功后所有参数配置会缓存到本地,此方法建议在初始化时调用:

    public Task FetchDataAsync() {
      DebugLog("Fetching data...");
      System.Threading.Tasks.Task fetchTask = Firebase.RemoteConfig.FirebaseRemoteConfig.FetchAsync(
          TimeSpan.Zero);
      return fetchTask.ContinueWithOnMainThread(FetchComplete);
    }


    void FetchComplete(Task fetchTask) {
      if (fetchTask.IsCanceled) {
        DebugLog("Fetch canceled.");
      } else if (fetchTask.IsFaulted) {
        DebugLog("Fetch encountered an error.");
      } else if (fetchTask.IsCompleted) {
        DebugLog("Fetch completed successfully!");
      }

      var info = Firebase.RemoteConfig.FirebaseRemoteConfig.Info;
      switch (info.LastFetchStatus) {
        case Firebase.RemoteConfig.LastFetchStatus.Success:
          //获取成功
          Firebase.RemoteConfig.FirebaseRemoteConfig.ActivateFetched();
          DebugLog(String.Format("Remote data loaded and ready (last fetch time {0}).",
                                 info.FetchTime));
          break;
        case Firebase.RemoteConfig.LastFetchStatus.Failure:
          /获取失败
          switch (info.LastFetchFailureReason) {
            case Firebase.RemoteConfig.FetchFailureReason.Error:
              DebugLog("Fetch failed for unknown reason");
              break;
            case Firebase.RemoteConfig.FetchFailureReason.Throttled:
              DebugLog("Fetch throttled until " + info.ThrottledEndTime);
              break;
          }
          break;
        case Firebase.RemoteConfig.LastFetchStatus.Pending:
          //等待中
          DebugLog("Latest Fetch call still pending.");
          break;
      }
    }

获取参数中的值

根据游戏业务场景来获取相应的值,从而做出不同的策略,获取示例如下:

      //参数的key由后台创建,请联系我方运营
      DebugLog("config_test_string: " +
               Firebase.RemoteConfig.FirebaseRemoteConfig.GetValue("config_test_string").StringValue);
      DebugLog("config_test_int: " +
               Firebase.RemoteConfig.FirebaseRemoteConfig.GetValue("config_test_int").LongValue);
      DebugLog("config_test_float: " +
               Firebase.RemoteConfig.FirebaseRemoteConfig.GetValue("config_test_float").DoubleValue);
      DebugLog("config_test_bool: " +
               Firebase.RemoteConfig.FirebaseRemoteConfig.GetValue("config_test_bool").BooleanValue);

3. Facebook接入

3.1 Facebook Analytics

集成Facebook SDK有助于Facebook投放端识别设备、安装回传,以及基础的数据统计。

3.1.1 导入SDK

下载地址

在Unity顶部菜单栏中选择Assets-->Import Package-->Custom Package,选择下载好的Facebook包,除了Examples目录下的文件,其他全部勾选,点击Import。

3.1.2 设置Facebook AppId

在Unity顶部菜单栏中选择 Facebook > Edit Settings,在Inspector面板中填入appid,appid从我方运营提供的参数文档中获取;

3.1.3 Android端额外配置

在Unity中配置好包名和最低API版本19,然后选择Facebook > Edit Settings,在面板Android Build Facebook settings中复制ClassName和debug key hash给我方运营。

注意,debug key hash是开发密钥,还需要一个正式发布密钥,需要根据发布时签名文件生成,生成方式参考此文档

将生成好的正式发布密钥也提供给我方运营。

4. 其他

4.1 合并AndroidManifest

如果在打包编译的时候出现Manifest合并相关的错误,可以把各个平台的Manifest需要配置的内容都添加在一个manifest文件中,把其他manifest都删除。

下面是各平台Manifest文件需要配置的内容:

    <!--MoPub GA Adjust必须配置-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--MoPub GA Adjust必须配置-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--Adjust 必须配置-->
    <uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />

    <application >
        <!--GA 必须配置-->
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        <!--MoPub 必须配置,注意Value值要替换成你的ADMOB_APP_ID-->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="[ADMOB_APP_ID]"/>

         <!-- MoPub 必须配置 -->
        <activity android:name="com.mopub.mobileads.MoPubActivity"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.mobileads.MraidActivity"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.common.MoPubBrowser"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.mobileads.MraidVideoPlayerActivity"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.mobileads.RewardedMraidActivity"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>
        <activity android:name="com.mopub.common.privacy.ConsentDialogActivity"
                  android:configChanges="keyboardHidden|orientation|screenSize"/>

        <!-- AdMob广告网络必须配置,如果你没有使用AdMob,可以移除此处配置  -->
        <activity android:name="com.google.android.gms.ads.AdActivity"
                  android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
                  android:theme="@android:style/Theme.Translucent"/>

        <!-- Facebook 广告网络必须配置,如果你没有使用Facebook,可以移除此处配置 -->
        <activity android:name="com.facebook.ads.AudienceNetworkActivity"
                  android:hardwareAccelerated="true" />

        <!-- IronSource 广告网络必须配置,如果你没有使用IronSource,可以移除此处配置 -->
        <activity android:name="com.ironsource.sdk.controller.ControllerActivity"
                  android:configChanges="orientation|screenSize"
                  android:hardwareAccelerated="true" />
        <activity android:name="com.ironsource.sdk.controller.InterstitialActivity"
                  android:configChanges="orientation|screenSize"
                  android:hardwareAccelerated="true"
                  android:theme="@android:style/Theme.Translucent" />
        <activity android:name="com.ironsource.sdk.controller.OpenUrlActivity"
                  android:configChanges="orientation|screenSize"
                  android:hardwareAccelerated="true"
                  android:theme="@android:style/Theme.Translucent" />

        <!-- UnityAds 广告网络必须配置,如果你没有使用Unity Ads,可以移除此处配置 -->
        <activity android:name="com.unity3d.ads.android.view.UnityAdsFullscreenActivity"
                  android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
                  android:hardwareAccelerated="true"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/>

        <!-- Vungle 广告网络必须配置,如果你没有使用Vungle,可以移除此处配置 -->
        <service  android:name="com.vungle.publisher.VungleService"
                  android:exported="false"/>

    </application>

4.1 各平台官网链接

MoPub

AdMob

Firebase

Adjust

Facebook

4.2 关于PlayServicesResolver

PlayServicesResolver是用于自动下载和解析Android和IOS所需要的依赖,各个平台可能会有不同的版本,集成时只要最新的版本即可,其他版本的不要重复添加,重复添加了需要把低版本的删除。

PlayServicesResolver一般会在项目打开时自动进行解析,如果PlayServicesResolver没有进行自动解析,也可以在Assets-->Play Services Resolver-->Android Resolver-->Resolver进行手动解析。

4.3 混淆配置

 -keep public class com.adjust.sdk.** { *; }
 -keep class com.google.android.gms.common.ConnectionResult {
    int SUCCESS;
 }
 -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
    com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
 }
 -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
    java.lang.String getId();
    boolean isLimitAdTrackingEnabled();
 }
 -keep public class com.android.installreferrer.** { *; }

4.4 FAQ

4.4.1 64k分包处理

处理步骤:

1)菜单栏中选择File-->BuildSetting-->在Platform中选择Android-->点击PlayerSetting-->Inspector面板中点击Publisher Setting。

​ 在Build模块中的BuildSystem选择Gradle,勾选Custom Gradle Template,然后Gradle文件就会出现在Assets\Plugins\Android\mainTemplate.gradle;

2)在build.gradle文件中defaultConfig里添加multiDexEnabled true;

3)在build.gradle文件中dependencies里面添加 compile 'com.android.support:multidex:1.0.3';

4)在AndroidManifest文件的application标签里添加name属性:android:name="android.support.multidex.MultiDexApplication";

build.gradle文件示例如下: