移动/游戏
在 Unity 游戏中集成 LevelPlay 广告聚合…
当需要给 Unity 游戏接入 LevelPlay 广告聚合(激励/插屏/横幅广告、广告网络配置、SDK 升级或从 IronSource/Unity Ads 迁移)时,按顺序走完安装、依赖解析、隐私配置、初始化、广告位实现与测试的完整流程。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 Unity 游戏中集成 LevelP特定
解决思路
- 先判断任务类型:询问用户是「全新集成」「迁移(旧 SDK 升级、替换 IronSource.Agent API、从 Unity Ads 迁移、Maven Central 构建失败)」还是「排障/在已有集成上追加功能」。迁移则读 references/migration-sdk-9.md,确认属于 A=SDK 升级、B=init API 迁移、C=广告位 API 迁移、D=Maven Central 构建失败、E=Unity Ads 迁移 中的哪一种,按对应场景执行;改完代码后走 Migration Completeness Checklist(该参考的 C5 节),再让用户检查 Unity 控制台编译错误并修复。
- 验证 Unity 环境:确认存在 Assets/ 和 ProjectSettings/ 目录;若不在项目根目录,让用户切换到 Unity 项目顶层目录并确认能看到这两个目录。
- 先了解业务目标:询问「你的主要优化目标是什么?」(收入优先 / 体验优先 / 平衡 / 还不确定),记录答案供第 8 步推荐广告位策略使用;选「还不确定」则默认按平衡策略处理。
- 通过 UPM 安装 LevelPlay SDK:Unity → Window > Package Manager → 选 Unity Registry 或 Services 标签 → 搜索 Ads Mediation → 确认包名精确为 Ads Mediation(不要装 Ads IAP Mediation Adaptor,也不要装已废弃的 Advertisement Legacy)→ 点 Install → 等待下载导入;若弹出安装 Mobile Dependency Resolver 的提示,点 Import。
- 安装后必须读项目文件验证,而不是问用户或相信 Package Manager 窗口:检查 Packages/manifest.json 的 dependencies 中是否有 com.unity.services.levelplay,并检查 Packages/packages-lock.json 中该 id 是否已解析出具体版本。这是硬性关卡:在 packages-lock.json 出现该 id 之前,不要写任何一行 LevelPlay 代码。若 manifest.json 有而 lock 文件没有,说明 Unity 尚未解析(可能仍在导入或解析失败),说明情况并停下;若 id 是你自己写进 manifest.json 且此后没跑过 Editor,lock 文件没有它是正常的,绝不要手写 packages-lock.json,而是让用户打开 Unity Editor 触发解析后重新读取。报告实际解析到的版本号。
- 随时可通过 Ads Mediation > Network Manager 安装额外广告网络适配器、检查 SDK 与适配器更新;iOS 构建稍后需要配置 SKAdNetwork(届时读 references/ios-setup.md)。
- 解析原生依赖(关键步骤):先问「你目标平台是 iOS、Android 还是两者?」,记录答案。通过 File ▸ Build Profiles(Unity 6 之前叫 Build Settings)→ Switch Platform 把活动构建目标切到 Android 或 iOS(LevelPlay 只在 Android/iOS 目标上运行,Standalone/PC/Mac 下连 Editor 里的 mock 广告都不生效)。按 references/dependency-resolution.md 走完整流程:检查是否已有依赖管理器(MDR、UEDM 或 EDM4U)、分别对 Android 与 iOS 解析、没有则安装、验证,以及旧版本的 Custom Main Gradle Template;若同时面向 Android 和 iOS,两者都要解析完再继续。询问「你是否已在目标平台上无错误地跑完依赖解析?」。Android API 33+ 需在 AndroidManifest.xml 中声明 <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>,否则 Android 13+ 上无法访问广告 ID。依赖解析失败时看 references/troubleshooting.md 的 gradle 与 CocoaPods 指引。
- 获取 App Key 与广告位 ID:在 LevelPlay 后台 https://platform.ironsrc.com/ 中,App Key 位于左侧 Apps → 选中应用 → 复制应用标题下的字母数字串;广告位 ID 位于左侧 Ad units → 选应用 → 复制各格式(Rewarded、Interstitial、Banner)的 ID。初始化(第 7 步)现在就需要 App Key;广告位 ID 到第 9 步才用,若还没决定格式可先只拿 App Key。
- 若使用 AdMob 作为聚合网络:在 Unity Editor 中 Ads Mediation > Developer Settings > LevelPlay Mediation Settings 配置 Android App Key 与 iOS App Key。若看不到 Ads Mediation 菜单,确认 Ads Mediation 包已安装(第 3 步)并重启 Unity Editor。
- 按需配置隐私与合规设置(先问用户是否需要为 GDPR、CCPA/CPRA 或儿童向应用配置隐私设置)。所有隐私设置必须在 SDK 初始化之前调用。GDPR:SDK 9.5.0+ 用 LevelPlayPrivacySettings.SetGDPRConsent(true/false);SDK 9.4.x 用 LevelPlayPrivacySettings.SetGDPRConsents(new Dictionary<string, bool> { {"UnityAds", true}, {"IronSource", true} })(按已安装网络逐项添加,完整网络 key 列表见 references/privacy-settings.md;该 API 在 9.4.x 是当前 API,不要误称为已废弃,它到 9.5.0+ 才标记 [Obsolete])。若两个 API 都编译不过,说明包/SDK 低于 9.4.0,建议通过 Ads Mediation > Network Manager 升级;无法升级则用 references/privacy-settings.md 中的旧版 LevelPlay.SetConsent(bool)。CCPA(9.4.0+)用 LevelPlayPrivacySettings.SetCCPA(true);COPPA(9.4.0+)用 LevelPlayPrivacySettings.SetCOPPA(true);CCPA/COPPA 编译失败则通过 Network Manager 升级。以上都在第 7 步 LevelPlay.Init() 之前调用。iOS 构建无论是否有上述法规要求,都必须在 LevelPlay.Init() 之前实现 ATT 授权(Apple 在 iOS 14.5+ 要求,且影响个性化广告与填充率),代码见 references/ios-setup.md。若无需隐私法规且不面向 iOS,跳过本步。
- 初始化 LevelPlay SDK:再次读 Packages/packages-lock.json 确认 com.unity.services.levelplay 存在(每次到这一步都要重读,即使之前已通过;之前对话说装好了不算证据)。然后让用户确认:第 4 步依赖解析无错误、第 5 步已复制 App Key、第 6 步(仅当用 AdMob)已在 Editor 配好 AdMob key。若包 id 缺失或用户答 NO/不确定:包缺失会导致 CS0246 → 回第 3 步;缺第 4 步 → 构建会失败 → 回第 4 步;缺第 5 步 → 没有凭据 → 回第 5 步;在全部确认前不要给 C# 代码。
- ILRD 可选接线:逐字询问「Do you use an analytics or attribution platform (Firebase, AppsFlyer, Adjust, Singular, or custom backend) that needs ad revenue data? If yes, the init script will include a logging stub for Impression Level Revenue (ILRD) — 3 lines of code, no analytics platform setup required yet. (Yes / No / Not sure — defaults to yes)」并记录答案。
- 询问初始化方式,完整列出四个选项(不要压缩或省略):1) 新建专用的 LevelPlay 初始化脚本;2) 加到已有的初始化/管理脚本里;3) 新建 LevelPlay 脚本并由已有管理器引用;4) 只给我初始化代码,我自己决定怎么集成。各选项完整代码见 references/initialization-api.md 的 Code Organization Options。注意:若第 6.5 步已为 iOS 配好 ATT,选项 1 要用 references/ios-setup.md Part 3 的 LevelPlayInitializer.cs(IEnumerator Start() 协程版本);选项 4 只提供完整的选项 1 初始化类作为独立片段,不要创建文件或加 Inspector/GameObject 设置步骤,并附注「保存为 LevelPlayInitializer.cs,挂到首个场景的常驻 GameObject 上,在 Inspector 里填 App Key」。
- 按 SDK 版本接 ILRD(版本在 Ads Mediation > Network Manager 查看):SDK 9.5.0+ 不要在初始化器里加任何东西,ILRD 通过每个广告实例的 OnAdImpressionDataReady 在第 9 步创建广告时接线(全局 LevelPlay.OnImpressionDataReady 在 9.5.0+ 已废弃并会产生编译警告,不要用);SDK 9.4.x 及更早则在 LevelPlay.Init() 之前订阅全局 LevelPlay.OnImpressionDataReady,加日志桩,并在 OnDestroy() 中取消订阅(iOS 协程初始化器要把订阅放在 InitializeLevelPlay() 内、LevelPlay.Init(appKey) 之前)。各选项精确接线代码见 references/initialization-api.md 的 Version-Aware ILRD Init Wiring。ILRD 回调在 mock 广告下不触发,需真机构建验证。
- 推荐广告位策略:回顾第 2 步的优化目标(对话过长则确认一次)。收入优先 → 收入策略:激励(主要变现,多个高价值时机)→ 插屏(次要,转场处,频次上限 3–5 分钟)→ 横幅(游戏过程中常驻),实现优先级 激励 → 插屏 → 横幅,bid floor 是可选的收入杠杆在第 9 步配置。体验优先 → 体验策略:仅激励、用户主动触发、高价值奖励、绝不做强制广告;插屏可选且仅在会话边界少量使用;横幅一般避免或仅菜单用;实现优先级 仅激励,或 激励 →(可选)插屏。平衡 → 平衡策略:激励(2–3 个战略位置)→ 插屏(适度,自然断点,频次上限 5–7 分钟)→ 横幅(选择性,菜单/低注意力场景);实现优先级 激励 → 插屏 → 横幅(选择性)。「还不确定」→ 用平衡策略并说明可随时改口。仍不清楚则问「你更看重收入、用户体验,还是两者平衡?」。用户想换顺序就按用户的来。
- 实现广告位:先读 references/best-practices.md,把其 Code Generation Guidelines (Step 9) 中的通用广告生命周期、各组织方式的代码生成规则、必含项(MonoBehaviour、OnDestroy() 中 DestroyAd()、使用 placement 时的 placement 频次上限检查、事件取消订阅、空值检查、错误处理)以及 bid floor 接线示例,套用到所有广告实现中。
- 实现前确认初始化:问用户「第 7 步 SDK 初始化完成了吗?Unity 控制台是否出现 'LevelPlay SDK initialized successfully' 日志?」答 NO 或不确定则回第 7 步,初始化确认可用前不要给广告实现代码。
- 询问要实现哪些广告格式:「Which ad formats do you want to implement? Rewarded, Interstitial, Banner, or a combination?」只实现用户选择的格式,之后可用「Adding More Ad Formats Later」追加。
- 在生成任何代码前先问代码组织方式:「How would you like to structure your ad implementation?」1) 每种格式独立管理器脚本(RewardedAdManager.cs、InterstitialAdManager.cs、BannerAdManager.cs,适合大项目、职责清晰);2) 单个统一的 AdManager.cs 处理所有格式(更简单、集中一处);3) 只给代码片段,我自己集成;4) 我已有广告管理器代码,帮我审查/修复/更新。按回答调整输出(见 references/best-practices.md 的代码生成指引)。若用户提到已有广告代码,无论选哪个选项都先让他把代码发来再生成,以便做针对性修复而不是从头写。
- 展示可选 bid floor 功能(选项 4 跳过,改为审查已有代码):只针对本次要实现的格式给出起始区间——Rewarded: $0.50–$2.00 | Interstitial: $0.20–$1.00 | Banner: $0.05–$0.20。话术:「可选——进阶:Bid Floors。多数发行商初期会跳过,等有真实后台数据再加。现在跳过完全没问题,之后随时可回来加。若现在要设:bid floor 为每个广告位设最低出价(USD),提高平均 eCPM 但降低填充率。起始区间:[本次实现的格式区间]。按格式回复数值,或直接说 'skip'。」按格式记录答案,给了值的格式在广告构造中接 Config.Builder().SetBidFloor(...),标 skip 的用基础构造函数(示例见 references/best-practices.md)。
- 若选选项 4(已有代码):先要代码并等待。分析是否使用当前 LevelPlay Ad Unit API(LevelPlayRewardedAd、LevelPlayInterstitialAd、LevelPlayBannerAd)、是否用了已废弃的 IronSource.Agent API、回调注册/取消订阅是否正确、是否缺错误处理或存在内存泄漏。若用废弃 API,说明如何迁移到新 LevelPlay Ad Unit API(详见 references/migration-sdk-9.md,init 看 Scenario B,各广告格式看 Scenario C 含 C5 完整性清单);若用当前 API 但有问题,指出具体问题并给修复;若实现正确,肯定并问要加哪些格式。修复以代码片段给出或建议重构;审查后再加新格式时,bid floor 提示只针对新格式,并确认沿用原有组织方式还是新起一种,然后按选项 1–3 的同样指引执行。
- 按格式读对应参考实现:激励广告 references/rewarded-api.md;插屏广告 references/interstitial-api.md;横幅广告 references/banner-api.md。
- ILRD 转发到分析平台(Firebase、AppsFlyer、Adjust、Singular 或自建后端)见 references/ilrd-api.md,按版本区分:SDK 9.5.0+ 在每个广告对象创建后立即订阅其 OnAdImpressionDataReady 并在 OnDestroy() 取消订阅,生成的每个广告管理器都要加;SDK 9.4.x 及更早用全局 LevelPlay.OnImpressionDataReady,在第 7 步初始化脚本中接线(用户在第 7 步答 Yes/不确定则已接好;若当时答 No 现在想加,在已有 LevelPlay.Init() 调用之前订阅)。
- 测试与验证(读 references/testing-and-validation.md):早期开发用 Editor 里的 mock 广告快速迭代和测回调——按 Play 会自动提供 mock 广告,但仅当活动构建目标是 Android 或 iOS(Standalone/PC/Mac 不出广告,这是「Editor 里没广告」最常见原因);mock 广告可用任意 App Key/广告位 ID,但建议用真实凭据以免忘记;mock 广告会触发多数回调(OnAdLoaded/Displayed/Rewarded/Closed),但不触发失败、点击和 impression/ILRD 回调,所以错误处理要在真机测。集成验证用 LevelPlay Test Suite(推荐,在真机上对真实广告网络做全面验证):在 LevelPlay.Init() 之前调用 LevelPlay.SetMetaData("is_test_suite", "enable"),在 OnInitSuccess 中调用 LevelPlay.LaunchTestSuite();必须真机构建(Editor 里不生效),开启 Development Build 以看到 SDK 日志,使用生产 App Key;发布前必须删掉这两行;iOS 协程初始化器要把 SetMetaData 放在 InitializeLevelPlay() 内第一行、Init 之前(不是放在 Start() 里)。把这两行加到已有的 LevelPlayInitializer.cs,不要新建文件。
- 发布前检查清单:Test Suite 在真机验证通过;所有已实现格式(激励、插屏、横幅)能正确加载;所有回调按预期触发;App Key 与广告位 ID 确认为生产值;在多种设备上测试(不同屏幕尺寸、OS 版本);iOS 专项(若面向 iOS):Info.plist 配好 SKAdNetwork ID、实现 ATT 框架、按需配置 iOS 隐私清单、在真机(非仅模拟器)测试;Android 专项(若面向 Android):Google Play Services 依赖已解析(第 4 步完成)、面向 API 33+ 时 AndroidManifest.xml 已加 AD_ID 权限、在真机测试;在生产环境用真实广告测试;插屏已实现频次上限;错误处理正确(用飞行模式测试——广告应优雅失败,不崩溃、不阻塞游戏)。
- 后续追加广告格式:直接跳到第 9 步,不必重做初始设置;先看 Unity 控制台确认 'LevelPlay SDK initialized successfully' 日志以验证已有初始化仍正常;选择要新增的格式;沿用之前的组织方式(独立脚本就新建对应管理器脚本,统一 AdManager 就往里加,代码片段就按同样模式集成);按第 9 步同样指引实现;按第 10 步测试。例如原先只用独立脚本实现了激励,现在加插屏:仿照 RewardedAdManager.cs 新建 InterstitialAdManager.cs,按 references/interstitial-api.md 的插屏指引实现,在 Editor 和真机测试;已有格式不受影响。
- 实现广告代码前先读 references/best-practices.md,把其中的加载策略(按格式)、投放位置策略、错误处理与优雅降级、内存管理、频次管理、常见错误规避等模式套用到所有广告实现中。
- 遇到问题时按症状路由到 references/troubleshooting.md 对应条目并直接给出修复(该指引说停止生成代码时就停),不要等用户自己去翻参考:CS0246/Unity.Services.LevelPlay 报红 → 包未安装,停止给代码,检查 packages-lock.json,安装(第 3 步),重启 Editor 后继续;Android gradle / iOS 构建依赖错误(Editor 能编译但构建失败)→ 原生依赖未解析,走第 4 步/dependency-resolution.md,验证 Assets/Plugins/Android/ 后重建;广告不加载 → SDK 未初始化、App Key 错误、广告在 init 前创建或无网络,确认 OnInitSuccess 先于创建广告触发、检查 App Key、真机测试;回调不触发 → 事件在 init 后注册、漏订阅或脚本被销毁,在 Init() 前注册回调、核对订阅、用常驻 GameObject;平台相关构建错误(iOS SKAdNetwork/ATT/frameworks;Android Play Services/manifest/gradle)→ 平台设置不完整,看 troubleshooting.md 与 references/ios-setup.md;Android 构建无法从 android-sdk.is.com 解析 com.ironsource.sdk 依赖(以前正常、什么都没改)→ 依赖已迁到 Maven Central、旧 is.com 仓库已关闭,按 references/migration-sdk-9.md Scenario D 删除过时的依赖 XML、通过 Network Manager 重装、确认不再有 is.com 引用。
- 按用户当前任务读对应参考:dependency-resolution.md(第 4 步原生依赖解析或 gradle/CocoaPods 构建失败);initialization-api.md(第 7 步初始化代码组织选项与 ILRD 初始化接线,以及 user ID、分群、同意管理、高级配置);privacy-settings.md(GDPR、CCPA、COPPA 合规,含旧版 SetConsent 与完整网络 key 列表);ios-setup.md(iOS 构建——ATT、SKAdNetwork、iOS 协程初始化器);rewarded-api.md / interstitial-api.md / banner-api.md(第 9 步各广告格式实现);best-practices.md(第 8 步策略细节、第 9 步代码生成指引、优化与投放位置);ilrd-api.md(把 ILRD 接到分析平台);testing-and-validation.md(第 10 步 mock 广告与 Test Suite);troubleshooting.md(编译/构建错误、广告不加载、回调不触发);migration-sdk-9.md(从 IronSource 或旧 LevelPlay API 迁移、升级 SDK 到 9.x.x、从 Unity Ads 迁移、Maven Central 依赖构建失败,第 0 步)。
- 全程遵守核心规则:Editor 侧检查基于真实项目文件而非假设(读项目文件或让用户在 Editor 中确认),生成的 C# 脚本是给用户保存到项目里的 MonoBehaviour,不是用来内联执行的;本技能只覆盖 LevelPlay 集成路径,不覆盖其他聚合 SDK,用户明确问替代方案时只承认存在并指向对应厂商自己的文档,不描述、不评价、不比较竞品;只提供本技能描述的步骤、文件和配置,不主动基于通用知识加步骤、建文件或给建议,超出范围的问题先查技能与参考文件确认未覆盖,再用通用知识回答但不得因此把额外步骤或文件并入集成流程;严格按顺序一次一步执行,只问当前步骤的问题,不提前收集后续步骤信息,每个检查点等用户回复再继续;步骤指向参考文件时必须读该参考并用其内容,不用通用知识替代;第 7 步的四个初始化选项与第 9 步的四个组织选项要按原文完整呈现,第 7 步的 ILRD 问题要逐字询问。
适用边界 · 注意事项
- 不适用于其他广告聚合 SDK 的集成;用户明确询问替代方案时,只承认其存在并指向对应厂商自己的文档,不描述、不评价、不比较竞品。
- 在 packages-lock.json 中确认 com.unity.services.levelplay 已解析之前,不要写任何 LevelPlay 代码(否则会因 CS0246 全部报错);也不要手写 packages-lock.json 来伪造「已解析」。
- 活动构建目标不是 Android/iOS(如 Standalone/PC/Mac)时,LevelPlay 不运行,连 Editor 里的 mock 广告也不生效;Test Suite 必须真机构建,Editor 中不可用。