ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Unity游戏接入穿山甲广告SDK完整指南与避坑实录

Unity游戏接入穿山甲广告SDK完整指南与避坑实录 写Unity游戏接穿山甲广告SDK是我这几年做国内发行绕不开的一步。Unity做原型和逻辑确实快但广告SDK的坑往往不在Unity这边全在Android工程、混淆规则、权限配置和广告位状态这些看不见的地方。这篇文章我会把从零接入穿山甲广告SDK的完整流程、代码示例、编译问题、上线前检查全部过一遍重点是那些你照着官方文档也容易翻车的细节。这篇内容适合谁看正好在用Unity做国内安卓游戏、想加广告变现却卡在SDK接入阶段的开发者也适合那种Unity已经跑通了、但一导出工程就各种编译报错或者广告位始终没有填充的同学。文里所有操作我都按实际项目流程来写不会让你照着搞完还一脸懵。1. 项目梳理与前置判断1.1 为什么游戏广告变现会优先考虑穿山甲国内安卓游戏广告变现主流平台就那几家穿山甲、优量汇、百青藤。穿山甲在游戏行业覆盖率确实明显占优尤其是休闲、超休闲、模拟经营这类IAA应用内广告模式的产品。原因很简单填充率长期稳定eCPM在中轻度游戏领域经常能打到同类产品里的头部水平而且出价策略和流量调度相对灵活A/B测试做起来也顺手。当然选平台不能只看单价。我更看重的是穿山甲对Unity开发者的支持程度。官方直接提供Unity插件包把Android客户端和广告逻辑封了一层C#接口你不需要手写Android原生代码就能完成大部分接入工作。对于小团队和独立开发者来说这意味着接入成本直线下降。对比优量汇和百度联盟Unity侧不是没有方案但官方维护力度、更新频次、文档完整度穿山甲在国内算第一梯队。对比维度穿山甲优量汇百青藤Unity官方插件有持续更新有但更新节奏偏慢弱多依赖原生接入游戏类填充率高中上一般收益稳定性好稳定波动偏大接入复杂度低中中高聚合能力GroMore支持完善有自家聚合聚合能力一般这是基于我自己的接触体感不同品类数据会有差异。但如果你做的是国内安卓游戏先把穿山甲作为首接平台问题不大。1.2 接入前必须想明白的三件事第一你的游戏适合哪种广告类型。开屏、激励视频、插屏、Banner它们的场景完全不一样。开屏流量大但单价取决于用户质量激励视频是IAA产品的现金牛插屏对用户体验伤害大需要谨慎设计展示频次Banner说实话国内eCPM很低体系不成熟的产品不如不做。前期先想清楚主变现场景避免什么点位都接最后数据一塌糊涂。第二测试广告位和正式广告位要分开管理。开发阶段如果拿正式广告位疯狂请求很容易触发平台风控轻则广告位被限流重则账号出问题。穿山甲后台提供了测试广告位ID虽然测试位eCPM不会太好但足够验证流程。正式上线前一定记得切回自己的真实广告位。第三隐私合规是硬门槛。现在上架应用市场隐私政策、用户授权弹窗都是必查项。穿山甲SDK本身会采集设备信息用于广告推荐你必须在隐私政策里写清楚并且在用户同意隐私政策前不要初始化广告SDK。这一点很多人忽略等上架被拒才回头补非常被动。2. 开发环境与工程配置2.1 Unity工程怎么导Android才对IIS和模拟器都别碰先说你最容易踩的第一个坑不要直接在Unity里点Build生成APK而是勾选Export Project导出Android Studio工程再做二次配置。原因是穿山甲SDK对AndroidManifest的合并、Gradle依赖的冲突处理都有要求如果Unity直接出包很多配置你改不进去出了问题也没法定位。Unity版本方面建议优先使用2020.3 LTS以上版本。穿山甲Unity插件每个版本支持的Unity版本范围不完全一样老项目用2018或2019也能接入但后续SDK升级会遇到各种兼容性问题尤其是Gradle版本和AndroidX依赖。新项目直接上LTS版本能省掉一半的编译坑。脚本后端建议直接选IL2CPP。Mono打包虽然体积小、编译快但国内主流分发渠道和广告SDK的兼容性验证大多基于IL2CPP做的加上Mono在真机上性能不稳定与其上线后再换不如一开始就选IL2CPP。如果你有第三方热更需求那就更得用IL2CPP了Mono配热更在国内环境简直是灾难。模拟器问题必须提一句。穿山甲SDK在部分模拟器环境是拿不到广告填充的或者填充了但展示无效这跟SDK的设备识别策略有关。你本地做功能测试时最好直接拿真机跑。我见过好几个项目开发在模拟器里测了半天广告一直没填充最后换真机一次就过了。2.2 穿山甲开发者后台的配置流程去穿山甲官网注册开发者账号这一步要注意主体资质。个人开发者能申请但部分广告位类型和结算方式会受限公司主体权限更全。注册后进入开发者后台先创建应用应用名称要和你的包名对应。应用创建成功后在应用下新建广告位。广告位类型要提前选好开屏广告位、激励视频广告位、插屏广告位、Banner广告位、Native广告位等。每个广告位创建后都会生成一个广告位ID格式一般是数字串形如“9876543210”。这个ID后面会填到Unity工程里。这里有个容易忽略的点新创建的广告位默认状态是“未通过”还是“启用”取决于平台的审核机制。新广告位需要经过一次审核才能投放正式流量。所以时间规划上至少提前一周把广告位建好别等游戏要上线了才想起建广告位审核还没过只能干着急。3. 核心接入流程实操3.1 导入SDK与初始化直接卡在第一步的坑穿山甲官方Unity插件包下载后通常是.unitypackage或者一个Android工程内的aar资源直接把包拖进Unity工程属于最稳妥的操作。如果你拿到的是手动集成文档那就得把对应的aar文件放进Assets/Plugins/Android目录并配置好对应的Gradle依赖。导入完成后初始化代码放在游戏启动的最早时机。国内广告SDK的初始化越早越好因为要拉取配置、建立网络连接、做设备匹配这些都是耗时的。我一般把初始化放在启动场景里用一个不销毁的GameObject挂初始化脚本避免场景切换时被重复初始化。下面是穿山甲Unity侧的典型初始化代码框架具体类名和方法以官方最新文档为准using UnityEngine; using PangleAdSDK; // 具体命名空间看你的SDK版本 public class AdSdkInit : MonoBehaviour { private void Awake() { // 防止场景切换时销毁重复初始化会浪费性能 DontDestroyOnLoad(gameObject); if (Application.platform RuntimePlatform.Android) { // 第一个参数是穿山甲后台申请的APP_ID // 第二个参数是是否开启调试日志开发期开true上线前切回false PangleAdSDK.Pangle.Init(你的APP_ID, true); } } }初始化这块有几个容易被忽视的点。第一不要在多个地方重复调用Init接口重复初始化会导致SDK内部状态错乱。第二调试日志开发期打开是没问题的上线前一定记得关掉调试日志不仅会影响性能还会把设备信息打到日志里有合规风险。第三初始化必须在主线程调用不要在子线程、不要放在异步回调里执行。3.2 广告位接入激励视频、插屏、开屏三套代码一网打尽3.2.1 激励视频最核心的变现位激励视频是所有IAA游戏里最赚钱的位置用户主动点击看广告获得奖励广告完整播完才算有效。接入逻辑分两层请求广告和展示广告。请求广告一般在玩家即将进入可以看广告的场景时就提前拉取等到玩家点按钮时如果广告已经加载好直接展示如果还没加载好要么转圈等待要么给个文案提示。using UnityEngine; using PangleAdSDK; public class RewardAdManager : MonoBehaviour { // 激励视频广告位ID private string rewardAdId 你的激励视频广告位ID; private IRewardAd rewardAd; public void LoadRewardAd() { // 每个广告位ID对应一个广告实例重复创建实例会影响拉取效果 rewardAd PangleAdSDK.Pangle.CreateRewardAd(rewardAdId); rewardAd.OnLoad OnRewardAdLoad; rewardAd.OnError OnRewardAdError; rewardAd.OnShow OnRewardAdShow; rewardAd.OnClose OnRewardAdClose; // 加载广告第二个参数是用户ID用于服务端奖励校验没有就传空 rewardAd.Load(玩家唯一标识); } public void ShowRewardAd() { if (rewardAd ! null rewardAd.IsReady()) { rewardAd.Show(); } } private void OnRewardAdLoad() { } private void OnRewardAdError(string errorCode, string errorMsg) { } private void OnRewardAdShow() { } private void OnRewardAdClose() { } }激励视频的服务器回调校验是另一个重点。如果你做的是需要给用户发奖励的游戏强烈建议使用服务端激励校验Server Verify。游戏客户端收到广告关闭的回调后不能直接把奖励发给用户因为客户端回调可以被破解或伪造。正确的流程是广告回调里带上服务端校验的凭证游戏服务器拿着凭证和广告平台的服务端接口进行二次校验校验通过才发奖励。3.2.2 插屏广告变现效率高但对体验伤害也大插屏广告是用在场景切换、关卡结束这类自然停顿点的。代码结构上和激励视频很像但插屏的展示频次要严格控制。我见过一些产品为了冲收益每局结束都弹插屏结果用户留存率掉了三分之一。插屏广告位在穿山甲后台创建后建议在代码里做一层频次控制比如“每10分钟最多展示1次”或者“每天最多展示8次”。不要完全依赖后台的流量控制客户端自身要做好保护。3.2.3 开屏广告决定用户第一印象开屏广告通常是App冷启动后弹出来的第一个全屏广告。Unity游戏的启动流程比较特殊引擎初始化、场景加载都需要时间开屏广告的展示时机如果不对就会出现白屏时间被用户跳过、广告压根没展示的情况。我的做法是启动场景加载完成后延迟0.3秒到0.5秒再请求开屏广告展示因为开屏广告有超时机制错过展示窗口就会被丢弃。开屏广告是自动拉取并展示的调用完Fetch方法后SDK会在下次进入前台时自己弹出所以接入上注意请求时机即可。这三种广告位的接入流程整理成一张表方便对照广告位类型加载时机展示时机注意点开屏应用冷启动时自动展示无需手动调Show超时窗口短注意加载速度激励视频玩家进入游戏后预热玩家点击后调用必须接服务端奖励校验插屏场景切换前预加载自然停顿点展示控制频次避免影响留存3.3 AndroidManifest与Gradle配置细节这一步是很多Unity开发者直接崩溃的地方。Unity导出的工程里AndroidManifest.xml是生成出来的你要在Assets/Plugins/Android/AndroidManifest.xml里写好配置Unity打包时会自动合并进去。穿山甲SDK要求的权限不多但缺一个都会影响初始化或广告填充。manifest xmlns:androidhttp://schemas.android.com/apk/res/android uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE / uses-permission android:nameandroid.permission.ACCESS_WIFI_STATE / !-- 以下权限按需声明targetSdkVersion 31及以上建议动态申请 -- uses-permission android:nameandroid.permission.READ_PHONE_STATE / /manifest我遇到过最坑的问题是AndroidX依赖冲突。Unity2019以上版本默认使用AndroidX但穿山甲SDK的某些历史版本用的是旧版support库两者共存会导致ClassNotFoundException和运行时崩溃。解决方案只有两条一是升级穿山甲SDK到新版本新版本都支持AndroidX二是如果SDK版本撞上旧依赖需要在Gradle里统一强制AndroidX版本。Gradle配置里minSdkVersion至少16但穿山甲SDK新版本建议最低21。targetSdkVersion建议拉到30以上因为Android 11的设备要求、Android 12的隐私权限适配都需要对应的target版本。Unity工程导出后找到launcher模块的build.gradle把这两个配置改好不要直接改Unity主工程里的默认模板很容易改错模块。混淆规则也是必然遇到的。如果你开启了构建混淆穿山甲SDK的所有类必须keep住否则编译可能不报错但运行时各种ClassNotFoundException。官方文档里有一份ProGuard规则最核心的是-keep class com.bytedance.sdk.** { *; } -keep class com.bytedance.embedapplog.** { *; } -dontwarn com.bytedance.sdk.**如果用的是Unity自带构建流程直接在Assets/Plugins/Android/proguard-user.txt里加这些规则。注意Unity的混淆流程和Android原生差别很大如果不确定规则有没有生效最直接的办法是在Unity导出工程后检查minifyEnabled是否为true再到打包后的APK里确认相关类是否被保留。4. 常见编译与运行问题排查4.1 Unity编译报错合集每次接SDK都是一场Gradle战斗我必须说Unity接入广告SDK最耗时间的部分根本不是写代码而是搞定Gradle编译。下面这几个报错我几乎每个项目都见过。Gradle版本过低或过高导致的“Failed to apply plugin”报错。穿山甲SDK本身不强制要求Gradle版本但AGPAndroid Gradle Plugin版本和大版本不匹配就会炸。Unity2020.3默认用的Gradle版本比较老而新版的穿山甲SDK可能要求AGP 4.0以上。解决方案很简单但步骤容易漏先升级Unity版本到2020.3.36以上然后在导出工程后替换Gradle wrapper版本。“Duplicate class”报错是另一个高频问题。这多半是因为SDK自带的依赖和你其他依赖包重复了比如adtag、embedapplog这些基础组件。解决方法是全局搜索重复的jar或aar把其中一个排掉。很多Unity开发者不熟悉Gradle的exclude语法在Unity的CustomBaseGradleTemplate里配置依赖排除时需要注意闭包语法和AGP版本的匹配。“Manifest merger failed”报错一般是冲突标签导致的。最常见的冲突是uses-sdk、application、activity这些标签的attribute不兼容。后合入的Manifest优先级高如果穿山甲SDK的Manifest和你自己写的Manifest里都有同样的配置优先用tools:replace覆盖application android:name.MainActivity tools:replaceandroid:name /application4.2 广告加载失败与无填充错误码排查速查表广告加载失败是接入过程中最让人头大的问题。广告加载失败的原因五花八门网络问题、广告位状态、设备环境、SDK初始化失败、代码调用顺序错误。穿山甲SDK的错误码体系还算规律我给几个最常见的错误码含义排查方向20001广告位参数错误检查广告位ID是否正确、广告位类型是否匹配20004无广告填充换测试广告位、检查广告位状态、确认网络环境20012广告位没有权限广告位审核未通过后台查看审核状态20013广告位已关闭后台开启广告位并保存40002网络请求失败确认设备能联网不要用模拟器测试20101超时检查网络延迟重新拉取广告30001初始化未完成确保初始化已完成再加载广告不要并发调用30002加载过于频繁减少刷新频率广告加载做节流排查无填充问题最有效的一招是切到穿山甲官方提供的测试广告位ID。官方文档里列出了各类型的测试广告位直接填进去试如果能加载成功说明代码流程没问题问题出在广告位配置或设备环境如果测试位也加载失败那大概率是SDK集成出了问题。模拟器是“无填充”的重灾区。穿山甲的广告请求会校验设备真实性很多模拟器不通过校验自然没有填充。所以测试广告位也没填充时先换一台真机试试别急着怀疑代码。还有一类问题是国家或地区限制。穿山甲主要服务国内市场如果你测试设备注册的国家不在中国大陆或者手机系统语言、时区设置有异常可能影响广告匹配。纯国内产品基本不用考虑这个问题但如果你在海外开模拟器测试国内SDK就会遇到“永远没填充”的假象。4.3 上线后崩了很多崩溃是发布时保留的调试开关惹的祸上线崩溃这个问题我在几个项目里都栽过跟头。Debug日志开关没关、调试模式没关这些在开发期无所谓的配置到了release包却可能引起崩溃或性能问题。另一个常见问题是IL2CPP裁剪导致的原生代码缺失。Unity的IL2CPP会对托管代码做裁剪如果一个原生方法在裁剪过程中被误认为未使用而移除运行时就可能直接崩溃。这种问题很难靠代码定位一般是加link.xml文件把关键程序集或类标记为保留linker assembly fullnamePangleAdSDK type fullname* preserveall / /assembly /linker放在Assets/link.xml重新出包基本上就能解决。上线后广告加载速率异常也要警惕。如果你的游戏把广告请求逻辑放在Update里或者每帧都在检查某个广告位是否就绪都会造成大量无效请求。广告SDK的请求频率是有限制的频繁请求会导致被平台暂时限流。正确的做法是按生命周期来管理广告要么在场景加载时预加载要么在展示后立刻预加载下一次不要在上层做轮询。5. 性能与体验调优5.1 包体优化别让广告SDK成为体积大户穿山甲SDK整个集成进去包体影响大概是几MB到十几MB具体取决于你集成的是单sdk还是带聚合的GroMore还有各ABI架构下的so文件。Unity导出Android包默认会带arm64-v8a、armeabi-v7a、x86和x86_64四套ABI广告SDK的so库也分架构打包进去体积自然就上去了。实际上发行到国内安卓渠道x86和x86_64基本用不上可以考虑通过Unity的ABI过滤只保留arm64-v8a和armeabi-v7a。在Player Settings里把ARMv7和ARM64勾选上x86全去掉。这样既能有效缩减包体也基本不影响设备覆盖率。需要提醒的是如果游戏要上模拟器渠道x86架构不能随便去模拟器大多数是x86的去了之后模拟器表现异常。除了ABI检查一下SDK资源文件里有没有被重复导入的库。通常穿山甲Unity插件包解压后包含的资源已经相对精简但如果你之前手动集成了其他广告SDK同时两家SDK共用了一些第三方基础库比方说okhttp、gson这类的就很容易出现重复类也会白白增加包体。用Gradle的依赖分析工具看一下即可。5.2 广告场景体验控制展示时机与频次广告展示时机如果控制不好收益和体验会同时崩。以插屏为例我习惯在游戏里加一个“场景切换保护”的规则玩家从主菜单进入对局时不展示插屏等对局结束回合结算时才展示。这样既符合“自然停顿点”的用户心理也不会让玩家觉得广告打断了操作。激励视频有个细节点很多新手没注意玩家点击看广告的按钮后到广告完全出现之间可能有一段时间的延迟尤其是网络状态不好时。这期间如果玩家反复点击按钮会导致多个广告请求并发出现广告错乱或直接加载失败。我一般会在代码里加一个isShowing的开关广告展示期间锁住入口展示结束再解锁。频次控制还可以通过服务端下发配置来实现。对于线上运营客户端写死的频次规则很难灵活调整我后面做的项目基本都会在游戏自己的配置下发里加几个参数比如激励视频每日次数上限、插屏最小间隔分钟数。这样运营想改策略不用发新包。广告SDK提供的频次控制是给广告请求用的真正管理“玩家什么时候能看广告”的逻辑还是应该握在自己手里。还有一个关于音量的坑。穿山甲激励视频在播放时有自己的音量控制逻辑和游戏BGM、音效的音量系统是分开管理的。如果游戏UI里提供了音量调节按钮你需要留意游戏主音量和广告音量的同步问题否则玩家把游戏音效关了广告还是“炸耳朵”投诉会非常多。6. 上线前的最后检查清单6.1 正式广告位切换别拿测试位发正式包这个错误我以前也犯过紧张上线的时候忘了把测试位切回正式位结果玩家看到的全是测试广告收益白白少了一整天。广告位ID的切换没有捷径就是个细心活。建议在代码里用一个枚举或配置常量表来管理所有广告位ID正式测试各一套打包前强行检查一下关键文件。在Unity项目里我习惯把广告位配置单独扔到一个Json或ScriptableObject里打包脚本在构建的时候会根据当前是Debug还是Release模式自动选择对应的广告位ID。这样能从根本上杜绝正式包混入测试ID的问题。上线前再确认一次穿山甲后台的广告位状态。创建广告位之后要经过审核审核通过前广告位是无法获得填充的。所以务必在正式发版前至少提前一两天确认所有广告位审核状态都是通过的不要发完包才发现广告请求返回20004。6.2 隐私政策与应用市场合规国内安卓应用市场现在对隐私合规审核比较严格。穿山甲SDK作为广告SDK会收集设备信息比如运营商、设备型号、系统版本、网络类型等。你要在应用隐私政策中明确列出穿山甲SDK收集的信息范围和使用目的并在用户首次启动时弹窗征求同意。从代码层面讲这个要求带来一个明显的改动在用户同意隐私政策之前不能初始化穿山甲SDK。也就是说如果你之前把初始化放到了GameObject的Awake里那改成一个带条件的延迟初始化用户点击同意后再Init。各家穿山甲SDK版本对初始化的时机要求差异略大早期版本就算不初始化也不会崩但请求广告时返回异常现在的新版本更严格直接不初始化就报错。上架前建议做一次模拟用户首启的测试清空应用数据冷启动确认在未同意隐私政策前广告SDK没有网络请求、没有初始化日志、没有收集设备信息。这一步能避免相当多的市场审核驳回。6.3 崩溃监控与早期预警发布后的第一批用户数据特别关键。我通常会选择一个稳定的崩溃收集平台配合穿山甲后台的广告数据观察开屏曝光量、激励视频填充率、人均展示次数这几个指标。如果开屏曝光量远低于启动量说明开屏广告加载或展示环节有故障如果激励视频填充率突然从90%掉到50%以下优先排查广告位状态和流量策略。崩溃监控不要只看整体崩溃率要看广告进程或广告场景相关的崩溃。有些广告SDK的崩溃是不影响游戏主流程的但在用户侧表现为退出后台或切场景时一瞬间卡死这种崩溃率统计不到主线程里容易被忽略。因此真机测试时要刻意去点击广告、快速关闭广告、音视频切到后台等极端操作很多边角崩溃都是这么暴露出来的。我个人的习惯是正式上线后前两周每天看一次穿山甲后台的收益报表和错误率报表同时看崩溃平台的增量错误。两周之后改成每周看一次顺手把频次控制、广告位顺序这些运营参数再调一轮。最后再分享一个小技巧。每次发布新包前我会保留一份上一次正常版本的APK作为对照一旦新版出现广告问题直接跑对照包看是不是SDK版本升级导致的回归。广告SDK升级这种操作千万不要在发版前三天才做给SDK升级预留至少一周的观察期否则出了兼容性问题你根本来不及回滚。Unity和穿山甲两个团队的更新节奏都很快SDK升级后一些小调整往往都不写进更新日志里只有真机实测才能发现。你在广告接入上做到这个习惯后面的版本迭代会舒服非常多。
返回列表