nccgs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/.claude/agents/nccgs-accessibility-specialist.md +26 -0
  2. package/.claude/agents/nccgs-adversarial-reviewer.md +26 -0
  3. package/.claude/agents/nccgs-ai-programmer.md +26 -0
  4. package/.claude/agents/nccgs-analytics-engineer.md +26 -0
  5. package/.claude/agents/nccgs-art-direction-lead.md +26 -0
  6. package/.claude/agents/nccgs-audio-direction-lead.md +26 -0
  7. package/.claude/agents/nccgs-creative-director.md +26 -0
  8. package/.claude/agents/nccgs-documentation-manager.md +26 -0
  9. package/.claude/agents/nccgs-economy-designer.md +26 -0
  10. package/.claude/agents/nccgs-engine-programmer.md +26 -0
  11. package/.claude/agents/nccgs-game-design-lead.md +26 -0
  12. package/.claude/agents/nccgs-game-designer.md +26 -0
  13. package/.claude/agents/nccgs-gameplay-programmer.md +26 -0
  14. package/.claude/agents/nccgs-level-designer.md +26 -0
  15. package/.claude/agents/nccgs-live-ops-designer.md +26 -0
  16. package/.claude/agents/nccgs-localization-lead.md +26 -0
  17. package/.claude/agents/nccgs-narrative-lead.md +26 -0
  18. package/.claude/agents/nccgs-network-programmer.md +26 -0
  19. package/.claude/agents/nccgs-performance-analyst.md +26 -0
  20. package/.claude/agents/nccgs-producer.md +26 -0
  21. package/.claude/agents/nccgs-production-coordinator.md +23 -0
  22. package/.claude/agents/nccgs-programming-lead.md +26 -0
  23. package/.claude/agents/nccgs-prototyper.md +26 -0
  24. package/.claude/agents/nccgs-qa-engineer.md +26 -0
  25. package/.claude/agents/nccgs-qa-lead.md +26 -0
  26. package/.claude/agents/nccgs-release-engineer.md +26 -0
  27. package/.claude/agents/nccgs-release-lead.md +26 -0
  28. package/.claude/agents/nccgs-security-engineer.md +26 -0
  29. package/.claude/agents/nccgs-sound-designer.md +26 -0
  30. package/.claude/agents/nccgs-systems-designer.md +26 -0
  31. package/.claude/agents/nccgs-technical-architect.md +26 -0
  32. package/.claude/agents/nccgs-technical-artist.md +26 -0
  33. package/.claude/agents/nccgs-technical-director.md +26 -0
  34. package/.claude/agents/nccgs-tools-programmer.md +26 -0
  35. package/.claude/agents/nccgs-ui-programmer.md +26 -0
  36. package/.claude/agents/nccgs-unity-build-specialist.md +26 -0
  37. package/.claude/agents/nccgs-unity-content-specialist.md +26 -0
  38. package/.claude/agents/nccgs-unity-implementer.md +26 -0
  39. package/.claude/agents/nccgs-unity-rendering-specialist.md +26 -0
  40. package/.claude/agents/nccgs-unity-systems-specialist.md +26 -0
  41. package/.claude/agents/nccgs-unity-ui-specialist.md +26 -0
  42. package/.claude/agents/nccgs-ux-designer.md +26 -0
  43. package/.claude/agents/nccgs-verification-engineer.md +26 -0
  44. package/.claude/agents/nccgs-world-builder.md +26 -0
  45. package/.claude/agents/nccgs-writer.md +26 -0
  46. package/.claude/nccgs/THIRD_PARTY_NOTICES.md +13 -0
  47. package/.claude/nccgs/VERSION +1 -0
  48. package/.claude/nccgs/constitution.md +131 -0
  49. package/.claude/nccgs/hooks/agent-audit.mjs +10 -0
  50. package/.claude/nccgs/hooks/common.mjs +41 -0
  51. package/.claude/nccgs/hooks/post-compact.mjs +1 -0
  52. package/.claude/nccgs/hooks/pre-compact.mjs +8 -0
  53. package/.claude/nccgs/hooks/protect-git.mjs +22 -0
  54. package/.claude/nccgs/hooks/protect-write.mjs +17 -0
  55. package/.claude/nccgs/hooks/session-start.mjs +15 -0
  56. package/.claude/nccgs/hooks/session-stop.mjs +7 -0
  57. package/.claude/nccgs/protocols/agent-contract.md +34 -0
  58. package/.claude/nccgs/protocols/context-packets.md +13 -0
  59. package/.claude/nccgs/protocols/evidence.md +15 -0
  60. package/.claude/nccgs/protocols/model-routing.md +22 -0
  61. package/.claude/nccgs/protocols/orchestration.md +26 -0
  62. package/.claude/nccgs/protocols/unity-boundary.md +11 -0
  63. package/.claude/nccgs/settings.fragment.json +77 -0
  64. package/.claude/nccgs/studio.json +347 -0
  65. package/.claude/nccgs/tools/configure-models.mjs +39 -0
  66. package/.claude/nccgs/unity-skills-manifest.json +727 -0
  67. package/.claude/nccgs/workflow-catalog.json +317 -0
  68. package/.claude/rules/nccgs-canonical-docs.md +19 -0
  69. package/.claude/rules/nccgs-editor-tools.md +12 -0
  70. package/.claude/rules/nccgs-localization.md +12 -0
  71. package/.claude/rules/nccgs-networking.md +13 -0
  72. package/.claude/rules/nccgs-performance.md +14 -0
  73. package/.claude/rules/nccgs-rendering.md +16 -0
  74. package/.claude/rules/nccgs-security.md +13 -0
  75. package/.claude/rules/nccgs-tests.md +18 -0
  76. package/.claude/rules/nccgs-ui.md +14 -0
  77. package/.claude/rules/nccgs-unity-assets.md +21 -0
  78. package/.claude/rules/nccgs-unity-code.md +22 -0
  79. package/.claude/skills/accessibility-review/SKILL.md +14 -0
  80. package/.claude/skills/architecture-decision/SKILL.md +14 -0
  81. package/.claude/skills/asset-audit/SKILL.md +14 -0
  82. package/.claude/skills/audit/SKILL.md +16 -0
  83. package/.claude/skills/audit/references/dimensions.md +46 -0
  84. package/.claude/skills/balance-review/SKILL.md +14 -0
  85. package/.claude/skills/bug-triage/SKILL.md +14 -0
  86. package/.claude/skills/build-live-game/SKILL.md +317 -0
  87. package/.claude/skills/build-live-game/references/achievements.md +779 -0
  88. package/.claude/skills/build-live-game/references/apis.md +280 -0
  89. package/.claude/skills/build-live-game/references/authentication.md +437 -0
  90. package/.claude/skills/build-live-game/references/battlepass.md +860 -0
  91. package/.claude/skills/build-live-game/references/cloud-code.md +563 -0
  92. package/.claude/skills/build-live-game/references/cloud-save.md +474 -0
  93. package/.claude/skills/build-live-game/references/deployment.md +216 -0
  94. package/.claude/skills/build-live-game/references/player-account.md +813 -0
  95. package/.claude/skills/build-live-game/references/remote-config.md +96 -0
  96. package/.claude/skills/build-live-game/references/tooling.md +431 -0
  97. package/.claude/skills/closure/SKILL.md +14 -0
  98. package/.claude/skills/code-review/SKILL.md +14 -0
  99. package/.claude/skills/compatibility-review/SKILL.md +14 -0
  100. package/.claude/skills/context-pack/SKILL.md +14 -0
  101. package/.claude/skills/dependency-review/SKILL.md +14 -0
  102. package/.claude/skills/design/SKILL.md +20 -0
  103. package/.claude/skills/design-review/SKILL.md +14 -0
  104. package/.claude/skills/evidence-review/SKILL.md +14 -0
  105. package/.claude/skills/hotfix/SKILL.md +14 -0
  106. package/.claude/skills/implement-in-app-purchases/README.md +233 -0
  107. package/.claude/skills/implement-in-app-purchases/SKILL.md +158 -0
  108. package/.claude/skills/implement-in-app-purchases/references/api-notes.md +562 -0
  109. package/.claude/skills/implement-in-app-purchases/references/codeless-catalog.md +331 -0
  110. package/.claude/skills/implement-in-app-purchases/references/convert-adapty.md +268 -0
  111. package/.claude/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
  112. package/.claude/skills/implement-in-app-purchases/references/convert-revenuecat.md +275 -0
  113. package/.claude/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
  114. package/.claude/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +204 -0
  115. package/.claude/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +198 -0
  116. package/.claude/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +356 -0
  117. package/.claude/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +446 -0
  118. package/.claude/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +680 -0
  119. package/.claude/skills/implement-in-app-purchases/references/platform-notes.md +204 -0
  120. package/.claude/skills/implement-in-app-purchases/references/pre-check.md +205 -0
  121. package/.claude/skills/incident-recovery/SKILL.md +14 -0
  122. package/.claude/skills/initialize-ai-navigation/SKILL.md +95 -0
  123. package/.claude/skills/initialize-ai-navigation/references/navigation-system.md +794 -0
  124. package/.claude/skills/levelplay-unity-integration/CHANGELOG.md +57 -0
  125. package/.claude/skills/levelplay-unity-integration/README.md +74 -0
  126. package/.claude/skills/levelplay-unity-integration/SKILL.md +1126 -0
  127. package/.claude/skills/levelplay-unity-integration/references/banner-api.md +920 -0
  128. package/.claude/skills/levelplay-unity-integration/references/best-practices.md +536 -0
  129. package/.claude/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
  130. package/.claude/skills/levelplay-unity-integration/references/initialization-api.md +630 -0
  131. package/.claude/skills/levelplay-unity-integration/references/interstitial-api.md +899 -0
  132. package/.claude/skills/levelplay-unity-integration/references/ios-setup.md +491 -0
  133. package/.claude/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
  134. package/.claude/skills/levelplay-unity-integration/references/privacy-settings.md +608 -0
  135. package/.claude/skills/levelplay-unity-integration/references/rewarded-api.md +902 -0
  136. package/.claude/skills/localization/SKILL.md +135 -0
  137. package/.claude/skills/localization/references/api-notes.md +76 -0
  138. package/.claude/skills/localization/resources/L10nBatchProcessor.cs +69 -0
  139. package/.claude/skills/localization/resources/LocalizedFontAsset.cs +18 -0
  140. package/.claude/skills/localize-game/SKILL.md +14 -0
  141. package/.claude/skills/migrate-project/SKILL.md +21 -0
  142. package/.claude/skills/migrate-project/references/procedure.md +63 -0
  143. package/.claude/skills/milestone-review/SKILL.md +14 -0
  144. package/.claude/skills/new-unity-project/SKILL.md +179 -0
  145. package/.claude/skills/optimize-audio/SKILL.md +199 -0
  146. package/.claude/skills/optimize-audio/resources/audio-import-api.md +146 -0
  147. package/.claude/skills/optimize-audio/resources/platform-settings.md +48 -0
  148. package/.claude/skills/optimize-text-mesh-pro/SKILL.md +182 -0
  149. package/.claude/skills/optimize-web/SKILL.md +393 -0
  150. package/.claude/skills/optimize-web/resources/WebOptimizer.cs +21 -0
  151. package/.claude/skills/optimize-web/resources/toktx-examples.sh +11 -0
  152. package/.claude/skills/performance-audit/SKILL.md +14 -0
  153. package/.claude/skills/physics-3d-collision/SKILL.md +442 -0
  154. package/.claude/skills/physics-3d-collision/references/troubleshooting.md +41 -0
  155. package/.claude/skills/physics-3d-collision/resources/CollisionDebugger.cs +33 -0
  156. package/.claude/skills/plan-feature/SKILL.md +14 -0
  157. package/.claude/skills/playtest/SKILL.md +14 -0
  158. package/.claude/skills/project-stage/SKILL.md +14 -0
  159. package/.claude/skills/prototype-feature/SKILL.md +14 -0
  160. package/.claude/skills/qa-plan/SKILL.md +14 -0
  161. package/.claude/skills/release/SKILL.md +18 -0
  162. package/.claude/skills/release-readiness/SKILL.md +14 -0
  163. package/.claude/skills/retrospective/SKILL.md +14 -0
  164. package/.claude/skills/review/SKILL.md +16 -0
  165. package/.claude/skills/security-audit/SKILL.md +14 -0
  166. package/.claude/skills/setup-multiplayer-services/SKILL.md +39 -0
  167. package/.claude/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
  168. package/.claude/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
  169. package/.claude/skills/setup-multiplayer-services/references/examples.md +33 -0
  170. package/.claude/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
  171. package/.claude/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
  172. package/.claude/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
  173. package/.claude/skills/setup-vivox-voice-chat/SKILL.md +118 -0
  174. package/.claude/skills/setup-vivox-voice-chat/evals/.env.example +6 -0
  175. package/.claude/skills/setup-vivox-voice-chat/evals/README.md +101 -0
  176. package/.claude/skills/setup-vivox-voice-chat/evals/promptfooconfig.yaml +32 -0
  177. package/.claude/skills/setup-vivox-voice-chat/evals/tests/init-and-login.yaml +76 -0
  178. package/.claude/skills/setup-vivox-voice-chat/evals/tests/text-chat.yaml +65 -0
  179. package/.claude/skills/setup-vivox-voice-chat/evals/tests/voice-channels.yaml +74 -0
  180. package/.claude/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
  181. package/.claude/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
  182. package/.claude/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
  183. package/.claude/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
  184. package/.claude/skills/setup-vivox-voice-chat/references/voice-channels.md +90 -0
  185. package/.claude/skills/shader-graph-create-custom-node/SKILL.md +25 -0
  186. package/.claude/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
  187. package/.claude/skills/sprint-plan/SKILL.md +14 -0
  188. package/.claude/skills/sprite-editor/SKILL.md +66 -0
  189. package/.claude/skills/sprite-editor/references/api_reference.md +151 -0
  190. package/.claude/skills/sprite-editor/references/background.md +112 -0
  191. package/.claude/skills/sprite-editor/references/templates.md +72 -0
  192. package/.claude/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
  193. package/.claude/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
  194. package/.claude/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
  195. package/.claude/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
  196. package/.claude/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
  197. package/.claude/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
  198. package/.claude/skills/sprite-editor/scripts/README.md +134 -0
  199. package/.claude/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
  200. package/.claude/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
  201. package/.claude/skills/status/SKILL.md +16 -0
  202. package/.claude/skills/story-readiness/SKILL.md +14 -0
  203. package/.claude/skills/test/SKILL.md +16 -0
  204. package/.claude/skills/ui/SKILL.md +142 -0
  205. package/.claude/skills/ui-imgui/SKILL.md +186 -0
  206. package/.claude/skills/ui-imgui/references/gui-elements.md +156 -0
  207. package/.claude/skills/ui-imgui/references/templates.md +141 -0
  208. package/.claude/skills/ui-review/SKILL.md +14 -0
  209. package/.claude/skills/ui-ugui/SKILL.md +282 -0
  210. package/.claude/skills/ui-ugui/references/scrollview-setup.md +29 -0
  211. package/.claude/skills/ui-uitk/SKILL.md +235 -0
  212. package/.claude/skills/ui-uitk/references/common-issues.md +74 -0
  213. package/.claude/skills/ui-uitk/references/custom-elements.md +241 -0
  214. package/.claude/skills/ui-uitk/references/painter2d.md +282 -0
  215. package/.claude/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
  216. package/.claude/skills/ui-uitk/references/svg-icons.md +136 -0
  217. package/.claude/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
  218. package/.claude/skills/ui-uitk/references/uss-guide.md +138 -0
  219. package/.claude/skills/unity-cli/CHANGELOG.md +233 -0
  220. package/.claude/skills/unity-cli/SECURITY.md +22 -0
  221. package/.claude/skills/unity-cli/SKILL.md +414 -0
  222. package/.claude/skills/unity-cli/references/auth-license-cloud.md +146 -0
  223. package/.claude/skills/unity-cli/references/build-run-test.md +349 -0
  224. package/.claude/skills/unity-cli/references/collaboration.md +472 -0
  225. package/.claude/skills/unity-cli/references/config-hub.md +103 -0
  226. package/.claude/skills/unity-cli/references/diagnostics-maintenance.md +326 -0
  227. package/.claude/skills/unity-cli/references/editors-install.md +327 -0
  228. package/.claude/skills/unity-cli/references/integration-advanced.md +472 -0
  229. package/.claude/skills/unity-cli/references/projects-templates.md +574 -0
  230. package/.claude/skills/unity-package-management/SKILL.md +304 -0
  231. package/.claude/skills/unity-package-management/references/select-packages.md +108 -0
  232. package/.claude/skills/urp-postprocessing/SKILL.md +188 -0
  233. package/.claude/skills/urp-postprocessing/references/code-templates.md +119 -0
  234. package/.claude/skills/urp-postprocessing/references/effect-reference.md +86 -0
  235. package/.claude/skills/validate-urp-render-graph-renderer-feature/SKILL.md +269 -0
  236. package/.claude/skills/work/SKILL.md +36 -0
  237. package/.claude/skills/work/references/classification.md +41 -0
  238. package/.claude/skills/work/references/closure.md +50 -0
  239. package/.claude/skills/work/references/feature-contracts.md +32 -0
  240. package/.claude/skills/work/references/verification.md +26 -0
  241. package/CLAUDE.md +6 -0
  242. package/LICENSE +21 -0
  243. package/README.md +162 -0
  244. package/THIRD_PARTY_NOTICES.md +23 -0
  245. package/UPGRADING.md +32 -0
  246. package/VERSION +1 -0
  247. package/docs/ARCHITECTURE.md +73 -0
  248. package/docs/HUONG-DAN-MIGRATE-VA-SU-DUNG.md +324 -0
  249. package/docs/MIGRATION-MATRIX.md +23 -0
  250. package/docs/PROJECT-POLICY.md +67 -0
  251. package/docs/WORKFLOWS.md +61 -0
  252. package/package-assets/setup-vivox-voice-chat-evals.gitignore +7 -0
  253. package/package.json +41 -0
  254. package/scaffold/.nccgs/bugs/.gitkeep +1 -0
  255. package/scaffold/.nccgs/closures/.gitkeep +1 -0
  256. package/scaffold/.nccgs/context/.gitkeep +1 -0
  257. package/scaffold/.nccgs/decisions/.gitkeep +1 -0
  258. package/scaffold/.nccgs/evidence/.gitkeep +1 -0
  259. package/scaffold/.nccgs/features/.gitkeep +1 -0
  260. package/scaffold/.nccgs/migrations/.gitkeep +1 -0
  261. package/scaffold/.nccgs/playtests/.gitkeep +1 -0
  262. package/scaffold/.nccgs/project.yaml +103 -0
  263. package/scaffold/.nccgs/requirements.yaml +10 -0
  264. package/scaffold/.nccgs/reviews/.gitkeep +1 -0
  265. package/scaffold/.nccgs/state.md +40 -0
  266. package/scaffold/.nccgs/templates/agent-handoff.md +25 -0
  267. package/scaffold/.nccgs/templates/architecture-decision.md +27 -0
  268. package/scaffold/.nccgs/templates/closure-record.md +51 -0
  269. package/scaffold/.nccgs/templates/context-packet.yaml +17 -0
  270. package/scaffold/.nccgs/templates/evidence-record.md +23 -0
  271. package/scaffold/.nccgs/templates/feature-contract.md +35 -0
  272. package/scaffold/.nccgs/templates/migration-plan.md +40 -0
  273. package/scaffold/.nccgs/templates/waiver.md +11 -0
  274. package/scripts/cli.mjs +56 -0
  275. package/scripts/install.mjs +267 -0
  276. package/scripts/sync-unity-skills.mjs +126 -0
  277. package/scripts/validate.mjs +205 -0
  278. package/tests/framework.test.mjs +121 -0
@@ -0,0 +1,899 @@
1
+ # Interstitial Ads API Reference
2
+
3
+ ## Contents
4
+ - [Overview](#overview)
5
+ - [Key Characteristics](#key-characteristics)
6
+ - [Implementation Pattern](#implementation-pattern)
7
+ - [API Reference](#api-reference)
8
+ - [Data Types](#data-types)
9
+ - [Best Practices](#best-practices)
10
+ - [Common Issues](#common-issues)
11
+ - [Testing Checklist](#testing-checklist)
12
+
13
+ ## Overview
14
+
15
+ Interstitial ads are full-screen video or static ads shown at natural transition points in your app. They provide good revenue while maintaining acceptable user experience when placed thoughtfully.
16
+
17
+ ## Key Characteristics
18
+
19
+ - **Full-screen**: Takes over the entire screen
20
+ - **Skippable**: User can close after viewing
21
+ - **Best for**: Level transitions, game over, menu navigation, session breaks
22
+
23
+ ## Implementation Pattern
24
+
25
+ ### Basic Interstitial Implementation
26
+
27
+ ```csharp
28
+ using UnityEngine;
29
+ using Unity.Services.LevelPlay;
30
+
31
+ public class InterstitialAdManager : MonoBehaviour
32
+ {
33
+ private LevelPlayInterstitialAd interstitialAd;
34
+ private string adUnitId = "YOUR_INTERSTITIAL_AD_UNIT_ID";
35
+
36
+ void Start()
37
+ {
38
+ // Create the interstitial ad object using constructor
39
+ interstitialAd = new LevelPlayInterstitialAd(adUnitId);
40
+
41
+ // Register event listeners
42
+ interstitialAd.OnAdLoaded += OnAdLoaded;
43
+ interstitialAd.OnAdLoadFailed += OnAdLoadFailed;
44
+ interstitialAd.OnAdDisplayed += OnAdDisplayed;
45
+ interstitialAd.OnAdDisplayFailed += OnAdDisplayFailed;
46
+ interstitialAd.OnAdClicked += OnAdClicked;
47
+ interstitialAd.OnAdClosed += OnAdClosed;
48
+ interstitialAd.OnAdInfoChanged += OnAdInfoChanged; // Fires when the loaded ad updates after a new auction result
49
+
50
+ // Load the ad
51
+ LoadAd();
52
+ }
53
+
54
+ void OnDestroy()
55
+ {
56
+ // Unregister event listeners
57
+ if (interstitialAd != null)
58
+ {
59
+ interstitialAd.OnAdLoaded -= OnAdLoaded;
60
+ interstitialAd.OnAdLoadFailed -= OnAdLoadFailed;
61
+ interstitialAd.OnAdDisplayed -= OnAdDisplayed;
62
+ interstitialAd.OnAdDisplayFailed -= OnAdDisplayFailed;
63
+ interstitialAd.OnAdClicked -= OnAdClicked;
64
+ interstitialAd.OnAdClosed -= OnAdClosed;
65
+ interstitialAd.OnAdInfoChanged -= OnAdInfoChanged;
66
+
67
+ // Destroy the ad to free its native resources
68
+ interstitialAd.DestroyAd();
69
+ }
70
+ }
71
+
72
+ public void LoadAd()
73
+ {
74
+ Debug.Log("Loading interstitial ad...");
75
+ interstitialAd.LoadAd();
76
+ }
77
+
78
+ public void ShowAd()
79
+ {
80
+ if (interstitialAd.IsAdReady())
81
+ {
82
+ Debug.Log("Showing interstitial ad");
83
+ interstitialAd.ShowAd();
84
+ }
85
+ else
86
+ {
87
+ Debug.LogWarning("Interstitial ad is not ready yet");
88
+ }
89
+ }
90
+
91
+ // Event Callbacks
92
+ private void OnAdLoaded(LevelPlayAdInfo adInfo)
93
+ {
94
+ Debug.Log("Interstitial ad loaded successfully");
95
+ }
96
+
97
+ private void OnAdLoadFailed(LevelPlayAdError error)
98
+ {
99
+ Debug.LogWarning($"Interstitial ad failed to load: {error.ErrorMessage}");
100
+ // Retry loading after a delay
101
+ Invoke(nameof(LoadAd), 30f);
102
+ }
103
+
104
+ private void OnAdDisplayed(LevelPlayAdInfo adInfo)
105
+ {
106
+ Debug.Log("Interstitial ad displayed");
107
+ }
108
+
109
+ private void OnAdDisplayFailed(LevelPlayAdInfo adInfo, LevelPlayAdError error)
110
+ {
111
+ Debug.LogError($"Interstitial ad failed to display: {error.ErrorMessage}");
112
+ // Load a new ad
113
+ LoadAd();
114
+ }
115
+
116
+ private void OnAdClicked(LevelPlayAdInfo adInfo)
117
+ {
118
+ Debug.Log("Interstitial ad clicked");
119
+ }
120
+
121
+ private void OnAdClosed(LevelPlayAdInfo adInfo)
122
+ {
123
+ Debug.Log("Interstitial ad closed");
124
+ // Load the next ad
125
+ LoadAd();
126
+ }
127
+
128
+ private void OnAdInfoChanged(LevelPlayAdInfo adInfo)
129
+ {
130
+ // Optional: log or update analytics with the latest revenue estimate
131
+ Debug.Log($"Interstitial ad info changed - network: {adInfo.AdNetwork}, revenue: ${adInfo.Revenue}");
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Advanced: Frequency Capping
137
+
138
+ Implement time-based frequency capping to avoid showing ads too frequently:
139
+
140
+ ```csharp
141
+ using UnityEngine;
142
+ using Unity.Services.LevelPlay;
143
+
144
+ public class FrequencyCappedInterstitialManager : MonoBehaviour
145
+ {
146
+ private LevelPlayInterstitialAd interstitialAd;
147
+ private string adUnitId = "YOUR_INTERSTITIAL_AD_UNIT_ID";
148
+
149
+ // Frequency capping settings
150
+ private float minTimeBetweenAds = 300f; // 5 minutes in seconds
151
+ private float lastAdShownTime = -999f; // Time when last ad was shown
152
+
153
+ void Start()
154
+ {
155
+ // Create interstitial ad object
156
+ interstitialAd = new LevelPlayInterstitialAd(adUnitId);
157
+
158
+ // Register callbacks
159
+ interstitialAd.OnAdLoaded += OnAdLoaded;
160
+ interstitialAd.OnAdLoadFailed += OnAdLoadFailed;
161
+ interstitialAd.OnAdDisplayed += OnAdDisplayed;
162
+ interstitialAd.OnAdClosed += OnAdClosed;
163
+ interstitialAd.OnAdDisplayFailed += OnAdDisplayFailed;
164
+
165
+ // Load first ad
166
+ interstitialAd.LoadAd();
167
+ }
168
+
169
+ void OnDestroy()
170
+ {
171
+ if (interstitialAd != null)
172
+ {
173
+ interstitialAd.OnAdLoaded -= OnAdLoaded;
174
+ interstitialAd.OnAdLoadFailed -= OnAdLoadFailed;
175
+ interstitialAd.OnAdDisplayed -= OnAdDisplayed;
176
+ interstitialAd.OnAdClosed -= OnAdClosed;
177
+ interstitialAd.OnAdDisplayFailed -= OnAdDisplayFailed;
178
+
179
+ // Destroy the ad to free its native resources
180
+ interstitialAd.DestroyAd();
181
+ }
182
+ }
183
+
184
+ public void TryShowInterstitial()
185
+ {
186
+ // Check if enough time has passed since last ad
187
+ float timeSinceLastAd = Time.time - lastAdShownTime;
188
+
189
+ if (timeSinceLastAd < minTimeBetweenAds)
190
+ {
191
+ Debug.Log($"Frequency cap: {minTimeBetweenAds - timeSinceLastAd:F0}s until next ad");
192
+ return;
193
+ }
194
+
195
+ // Check if ad is ready
196
+ if (interstitialAd.IsAdReady())
197
+ {
198
+ interstitialAd.ShowAd();
199
+ }
200
+ else
201
+ {
202
+ Debug.LogWarning("Interstitial not ready, loading...");
203
+ interstitialAd.LoadAd();
204
+ }
205
+ }
206
+
207
+ private void OnAdLoaded(LevelPlayAdInfo adInfo)
208
+ {
209
+ Debug.Log("Interstitial loaded");
210
+ }
211
+
212
+ private void OnAdLoadFailed(LevelPlayAdError error)
213
+ {
214
+ Debug.LogWarning($"Interstitial load failed: {error.ErrorMessage}");
215
+ Invoke(nameof(LoadAd), 30f);
216
+ }
217
+
218
+ private void OnAdDisplayed(LevelPlayAdInfo adInfo)
219
+ {
220
+ Debug.Log("Interstitial displayed");
221
+ lastAdShownTime = Time.time; // Record when ad was shown
222
+ }
223
+
224
+ private void OnAdClosed(LevelPlayAdInfo adInfo)
225
+ {
226
+ Debug.Log("Interstitial closed");
227
+ // Load next ad
228
+ interstitialAd.LoadAd();
229
+ }
230
+
231
+ private void OnAdDisplayFailed(LevelPlayAdInfo adInfo, LevelPlayAdError error)
232
+ {
233
+ Debug.LogError($"Interstitial display failed: {error.ErrorMessage}");
234
+ interstitialAd.LoadAd();
235
+ }
236
+
237
+ private void LoadAd()
238
+ {
239
+ if (interstitialAd != null)
240
+ {
241
+ interstitialAd.LoadAd();
242
+ }
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### Advanced: Multiple Placements
248
+
249
+ Track different interstitial placements for analytics:
250
+
251
+ ```csharp
252
+ using UnityEngine;
253
+ using Unity.Services.LevelPlay;
254
+
255
+ public class MultiPlacementInterstitialManager : MonoBehaviour
256
+ {
257
+ private LevelPlayInterstitialAd interstitialAd;
258
+ private string adUnitId = "YOUR_INTERSTITIAL_AD_UNIT_ID";
259
+
260
+ // Placement names
261
+ private const string PLACEMENT_LEVEL_COMPLETE = "level_complete";
262
+ private const string PLACEMENT_GAME_OVER = "game_over";
263
+ private const string PLACEMENT_MAIN_MENU = "main_menu";
264
+
265
+ // Frequency capping per placement
266
+ private float minTimeBetweenAds = 300f;
267
+ private float lastAdTime = -999f;
268
+
269
+ void Start()
270
+ {
271
+ interstitialAd = new LevelPlayInterstitialAd(adUnitId);
272
+
273
+ interstitialAd.OnAdLoaded += OnAdLoaded;
274
+ interstitialAd.OnAdLoadFailed += OnAdLoadFailed;
275
+ interstitialAd.OnAdDisplayed += OnAdDisplayed;
276
+ interstitialAd.OnAdClosed += OnAdClosed;
277
+ interstitialAd.OnAdDisplayFailed += OnAdDisplayFailed;
278
+
279
+ interstitialAd.LoadAd();
280
+ }
281
+
282
+ void OnDestroy()
283
+ {
284
+ if (interstitialAd != null)
285
+ {
286
+ interstitialAd.OnAdLoaded -= OnAdLoaded;
287
+ interstitialAd.OnAdLoadFailed -= OnAdLoadFailed;
288
+ interstitialAd.OnAdDisplayed -= OnAdDisplayed;
289
+ interstitialAd.OnAdClosed -= OnAdClosed;
290
+ interstitialAd.OnAdDisplayFailed -= OnAdDisplayFailed;
291
+
292
+ // Destroy the ad to free its native resources
293
+ interstitialAd.DestroyAd();
294
+ }
295
+ }
296
+
297
+ // Public methods for different placements
298
+ public void ShowOnLevelComplete()
299
+ {
300
+ TryShowWithPlacement(PLACEMENT_LEVEL_COMPLETE);
301
+ }
302
+
303
+ public void ShowOnGameOver()
304
+ {
305
+ TryShowWithPlacement(PLACEMENT_GAME_OVER);
306
+ }
307
+
308
+ public void ShowOnMainMenu()
309
+ {
310
+ TryShowWithPlacement(PLACEMENT_MAIN_MENU);
311
+ }
312
+
313
+ private void TryShowWithPlacement(string placementName)
314
+ {
315
+ // Check frequency cap
316
+ if (Time.time - lastAdTime < minTimeBetweenAds)
317
+ {
318
+ Debug.Log($"Frequency cap active for {placementName}");
319
+ return;
320
+ }
321
+
322
+ // Check placement capping
323
+ if (LevelPlayInterstitialAd.IsPlacementCapped(placementName))
324
+ {
325
+ Debug.Log($"Placement {placementName} is capped");
326
+ return;
327
+ }
328
+
329
+ // Check if ad ready
330
+ if (interstitialAd.IsAdReady())
331
+ {
332
+ Debug.Log($"Showing interstitial with placement: {placementName}");
333
+ interstitialAd.ShowAd(placementName: placementName);
334
+ }
335
+ else
336
+ {
337
+ Debug.LogWarning("Interstitial not ready");
338
+ }
339
+ }
340
+
341
+ private void OnAdLoaded(LevelPlayAdInfo adInfo)
342
+ {
343
+ Debug.Log("Interstitial loaded");
344
+ }
345
+
346
+ private void OnAdLoadFailed(LevelPlayAdError error)
347
+ {
348
+ Debug.LogWarning($"Interstitial load failed: {error.ErrorMessage}");
349
+ Invoke(nameof(LoadAd), 30f);
350
+ }
351
+
352
+ private void OnAdDisplayed(LevelPlayAdInfo adInfo)
353
+ {
354
+ Debug.Log("Interstitial displayed");
355
+ lastAdTime = Time.time;
356
+ }
357
+
358
+ private void OnAdClosed(LevelPlayAdInfo adInfo)
359
+ {
360
+ Debug.Log("Interstitial closed");
361
+ interstitialAd.LoadAd();
362
+ }
363
+
364
+ private void OnAdDisplayFailed(LevelPlayAdInfo adInfo, LevelPlayAdError error)
365
+ {
366
+ Debug.LogError($"Interstitial display failed: {error.ErrorMessage}");
367
+ interstitialAd.LoadAd();
368
+ }
369
+
370
+ private void LoadAd()
371
+ {
372
+ if (interstitialAd != null)
373
+ {
374
+ interstitialAd.LoadAd();
375
+ }
376
+ }
377
+ }
378
+ ```
379
+
380
+ ## API Reference
381
+
382
+ ### Constructor
383
+
384
+ #### `new LevelPlayInterstitialAd(string adUnitId)`
385
+ Create an interstitial ad object.
386
+
387
+ **Parameters:**
388
+ - `adUnitId`: The ad unit identifier from your LevelPlay dashboard
389
+
390
+ **Returns:** `LevelPlayInterstitialAd` object
391
+
392
+ **Usage:**
393
+ ```csharp
394
+ LevelPlayInterstitialAd interstitialAd = new LevelPlayInterstitialAd("your_ad_unit_id");
395
+ ```
396
+
397
+ **Important:** Call this only after `LevelPlay.Init()` has completed successfully (in the `OnInitSuccess` callback).
398
+
399
+ #### `new LevelPlayInterstitialAd(string adUnitId, Config config)`
400
+ Create an interstitial ad object with custom configuration.
401
+
402
+ **Parameters:**
403
+ - `adUnitId`: The ad unit identifier
404
+ - `config`: Optional configuration object
405
+
406
+ **Usage:**
407
+ ```csharp
408
+ var configBuilder = new LevelPlayInterstitialAd.Config.Builder();
409
+ configBuilder.SetBidFloor(1.0); // Minimum bid price in USD
410
+ var config = configBuilder.Build();
411
+ LevelPlayInterstitialAd interstitialAd = new LevelPlayInterstitialAd("your_ad_unit_id", config);
412
+ ```
413
+
414
+ ### Configuration Builder
415
+
416
+ #### `LevelPlayInterstitialAd.Config.Builder()`
417
+ Create a configuration builder for interstitial ads.
418
+
419
+ **Returns:** `LevelPlayInterstitialAd.Config.Builder` object
420
+
421
+ **Usage:**
422
+ ```csharp
423
+ var configBuilder = new LevelPlayInterstitialAd.Config.Builder();
424
+ ```
425
+
426
+ **Set minimum bid price:**
427
+ ```csharp
428
+ configBuilder.SetBidFloor(1.0); // Minimum bid price in USD ($1.00 CPM)
429
+ ```
430
+
431
+ **When to use:** Set a minimum bid price in USD for ad requests.
432
+
433
+ #### `Build()`
434
+ Build the configuration object.
435
+
436
+ **Returns:** `LevelPlayInterstitialAd.Config` object
437
+
438
+ **Usage:**
439
+ ```csharp
440
+ var config = configBuilder.Build();
441
+ ```
442
+
443
+ ### Core Methods
444
+
445
+ #### `LoadAd()`
446
+ Load an interstitial ad.
447
+
448
+ **Usage:**
449
+ ```csharp
450
+ interstitialAd.LoadAd();
451
+ ```
452
+
453
+ **When to call:**
454
+ - After SDK initialization completes
455
+ - After showing an ad (to load the next one)
456
+ - After a load or display failure
457
+
458
+ #### `ShowAd()`
459
+ Show the interstitial ad without a placement name.
460
+
461
+ **Usage:**
462
+ ```csharp
463
+ if (interstitialAd.IsAdReady())
464
+ {
465
+ interstitialAd.ShowAd();
466
+ }
467
+ ```
468
+
469
+ **Important:** Always check `IsAdReady()` before calling `ShowAd()`.
470
+
471
+ #### `ShowAd(placementName: string)`
472
+ Show the interstitial ad with a named placement for analytics tracking.
473
+
474
+ **Parameters:**
475
+ - `placementName`: Placement name configured in LevelPlay dashboard
476
+
477
+ **Usage:**
478
+ ```csharp
479
+ interstitialAd.ShowAd(placementName: "level_complete");
480
+ ```
481
+
482
+ **When to use:** When tracking multiple placements within the same ad unit for analytics.
483
+
484
+ #### `IsAdReady()`
485
+ Check if an interstitial ad is loaded and ready to show.
486
+
487
+ **Returns:** `bool` - true if ready, false otherwise
488
+
489
+ **Usage:**
490
+ ```csharp
491
+ if (interstitialAd.IsAdReady())
492
+ {
493
+ // Ad is ready to show
494
+ interstitialAd.ShowAd();
495
+ }
496
+ else
497
+ {
498
+ // Ad not ready, load it
499
+ interstitialAd.LoadAd();
500
+ }
501
+ ```
502
+
503
+ #### `LevelPlayInterstitialAd.IsPlacementCapped(string placementName)` (Static)
504
+ Check if a placement has reached its capping limit.
505
+
506
+ **Parameters:**
507
+ - `placementName`: The placement name to check
508
+
509
+ **Returns:** `bool` - true if capped, false otherwise
510
+
511
+ **Usage:**
512
+ ```csharp
513
+ if (LevelPlayInterstitialAd.IsPlacementCapped("level_complete"))
514
+ {
515
+ Debug.Log("Level complete placement is capped");
516
+ }
517
+ ```
518
+
519
+ **When to use:** Before showing an ad to check if the placement frequency cap is reached.
520
+
521
+ ### Events
522
+
523
+ All events are properties of the `LevelPlayInterstitialAd` object.
524
+
525
+ **Threading:** All ad callbacks run on the Unity main thread, so you can safely call Unity APIs (update UI, access GameObjects, etc.) directly in these callbacks. This is different from the ILRD impression callback (see `references/ilrd-api.md`), which runs on a background thread.
526
+
527
+ #### `OnAdLoaded`
528
+ Fired when an interstitial ad is successfully loaded.
529
+
530
+ **Signature:** `event Action<LevelPlayAdInfo>`
531
+
532
+ **Usage:**
533
+ ```csharp
534
+ interstitialAd.OnAdLoaded += (adInfo) =>
535
+ {
536
+ Debug.Log("Interstitial ad loaded");
537
+ };
538
+ ```
539
+
540
+ #### `OnAdLoadFailed`
541
+ Fired when an interstitial ad fails to load.
542
+
543
+ **Signature:** `event Action<LevelPlayAdError>`
544
+
545
+ **Usage:**
546
+ ```csharp
547
+ interstitialAd.OnAdLoadFailed += (error) =>
548
+ {
549
+ Debug.LogWarning($"Load failed: {error.ErrorMessage}");
550
+ };
551
+ ```
552
+
553
+ **Best practice:** Implement retry logic with exponential backoff.
554
+
555
+ #### `OnAdDisplayed`
556
+ Fired when an interstitial ad is displayed on screen.
557
+
558
+ **Signature:** `event Action<LevelPlayAdInfo>`
559
+
560
+ **Usage:**
561
+ ```csharp
562
+ interstitialAd.OnAdDisplayed += (adInfo) =>
563
+ {
564
+ Debug.Log("Interstitial ad displayed");
565
+ // Optional: Track analytics
566
+ };
567
+ ```
568
+
569
+ #### `OnAdDisplayFailed`
570
+ Fired when an interstitial ad fails to display.
571
+
572
+ **Signature:** `event Action<LevelPlayAdInfo, LevelPlayAdError>`
573
+
574
+ **Usage:**
575
+ ```csharp
576
+ interstitialAd.OnAdDisplayFailed += (adInfo, error) =>
577
+ {
578
+ Debug.LogError($"Display failed: {error.ErrorMessage}");
579
+ // Load a new ad
580
+ interstitialAd.LoadAd();
581
+ };
582
+ ```
583
+
584
+ #### `OnAdClicked`
585
+ Fired when the user clicks on the interstitial ad.
586
+
587
+ **Signature:** `event Action<LevelPlayAdInfo>`
588
+
589
+ **Usage:**
590
+ ```csharp
591
+ interstitialAd.OnAdClicked += (adInfo) =>
592
+ {
593
+ Debug.Log("Interstitial ad clicked");
594
+ // Optional analytics tracking
595
+ };
596
+ ```
597
+
598
+ #### `OnAdClosed`
599
+ Fired when the interstitial ad is closed.
600
+
601
+ **Signature:** `event Action<LevelPlayAdInfo>`
602
+
603
+ **Usage:**
604
+ ```csharp
605
+ interstitialAd.OnAdClosed += (adInfo) =>
606
+ {
607
+ Debug.Log("Interstitial ad closed");
608
+ // Resume game, load next ad
609
+ interstitialAd.LoadAd();
610
+ };
611
+ ```
612
+
613
+ **Best practice:** Load the next ad immediately in this callback.
614
+
615
+ #### `OnAdInfoChanged`
616
+ Fired when ad information changes, such as when a new winning ad becomes available after auction.
617
+
618
+ **Signature:** `event Action<LevelPlayAdInfo>`
619
+
620
+ **Usage:**
621
+ ```csharp
622
+ interstitialAd.OnAdInfoChanged += (adInfo) =>
623
+ {
624
+ Debug.Log($"Ad info changed - New ad from: {adInfo.AdNetwork}");
625
+ Debug.Log($"Estimated revenue: ${adInfo.Revenue}");
626
+ };
627
+ ```
628
+
629
+ **Important:** This event indicates that a new ad with potentially different revenue has become available. The SDK automatically selects the winning ad from the auction when you call `ShowAd()`, but this event lets you know when the ad info has been updated. This is particularly important for revenue optimization as it signals when a new auction winner has loaded.
630
+
631
+ **When it fires:**
632
+ - After a new ad loads with different properties than the previous one
633
+ - When the waterfall selects a different ad network
634
+ - When ad auction results change
635
+
636
+ **Why it matters:** The updated `LevelPlayAdInfo` contains the latest revenue estimates and network information, which directly impacts your monetization. Always use the most recent `adInfo` when logging or analyzing ad performance.
637
+
638
+ **If you're using ILRD** (`references/ilrd-api.md`): the `LevelPlayImpressionData` you receive in the ILRD impression callback already contains the final revenue value, so `OnAdInfoChanged` is mostly useful for in-Editor debugging of the waterfall. Most publishers can leave it as a logging hook.
639
+
640
+ ## Data Types
641
+
642
+ ### LevelPlayAdInfo
643
+
644
+ Contains information about the ad.
645
+
646
+ **Properties:**
647
+ - `AdId` (string): Unique identifier for this specific ad instance
648
+ - `AdUnitId` (string): The ad unit identifier
649
+ - `AdUnitName` (string): The ad unit name
650
+ - `AdSize` (LevelPlayAdSize): The ad size (may be null; banner-relevant)
651
+ - `AdFormat` (string): The ad format (e.g., "INTERSTITIAL")
652
+ - `PlacementName` (string): Placement name where ad was shown
653
+ - `AuctionId` (string): Unique auction identifier
654
+ - `CreativeId` (string): Creative identifier
655
+ - `Country` (string): User's country code (ISO 3166-1)
656
+ - `Ab` (string): A/B test segment identifier
657
+ - `SegmentName` (string): User segment name
658
+ - `AdNetwork` (string): Ad network that served the ad
659
+ - `InstanceName` (string): Ad network instance name
660
+ - `InstanceId` (string): Ad network instance identifier
661
+ - `Revenue` (double?): Estimated revenue in USD (nullable - check for null)
662
+ - `Precision` (string): Revenue precision level
663
+ - `EncryptedCPM` (string): Encrypted CPM value
664
+
665
+ ### LevelPlayAdError
666
+
667
+ Contains error information when ad operations fail.
668
+
669
+ **Properties:**
670
+ - `ErrorCode` (int): Numeric error code
671
+ - `ErrorMessage` (string): Human-readable error description
672
+ - `AdUnitId` (string): The ad unit identifier where the error occurred
673
+ - `AdId` (string): Unique identifier for the specific ad instance
674
+
675
+ ## Best Practices
676
+
677
+ ### Loading Strategy
678
+
679
+ **Keep an interstitial ready for opportunistic moments:**
680
+ ```csharp
681
+ // Load after init
682
+ void OnInitSuccess(LevelPlayConfiguration config)
683
+ {
684
+ interstitialAd = new LevelPlayInterstitialAd(adUnitId);
685
+ interstitialAd.OnAdLoaded += OnAdLoaded;
686
+ interstitialAd.OnAdClosed += OnAdClosed;
687
+ interstitialAd.LoadAd();
688
+ }
689
+
690
+ // Reload after showing
691
+ void OnAdClosed(LevelPlayAdInfo adInfo)
692
+ {
693
+ interstitialAd.LoadAd();
694
+ }
695
+ ```
696
+
697
+ ### Placement Strategy
698
+
699
+ **Show at natural transition points:**
700
+ - ✅ Level complete screen
701
+ - ✅ Game over screen
702
+ - ✅ Returning to main menu
703
+ - ✅ Between sessions
704
+ - ❌ During active gameplay
705
+ - ❌ Mid-level or mid-action
706
+
707
+ ### Frequency Capping
708
+
709
+ **Implement time-based capping to avoid annoying users:**
710
+ ```csharp
711
+ private float minTimeBetweenAds = 300f; // 5 minutes
712
+ private float lastAdTime = -999f;
713
+
714
+ public void TryShowInterstitial()
715
+ {
716
+ if (Time.time - lastAdTime < minTimeBetweenAds)
717
+ {
718
+ Debug.Log("Too soon to show another ad");
719
+ return;
720
+ }
721
+
722
+ if (interstitialAd.IsAdReady())
723
+ {
724
+ interstitialAd.ShowAd();
725
+ }
726
+ }
727
+
728
+ private void OnAdDisplayed(LevelPlayAdInfo adInfo)
729
+ {
730
+ lastAdTime = Time.time;
731
+ }
732
+ ```
733
+
734
+ **Recommended frequencies:**
735
+ - **Revenue-focused**: 3-5 minutes
736
+ - **Balanced**: 5-7 minutes
737
+ - **UX-focused**: 7-10 minutes or never
738
+
739
+ ### User Flow
740
+
741
+ **Never block user progress waiting for ads:**
742
+ ```csharp
743
+ // ✅ CORRECT - Don't block flow
744
+ public void OnLevelComplete()
745
+ {
746
+ // Continue to next level regardless of ad
747
+ LoadNextLevel();
748
+
749
+ // Try to show ad, but don't wait for it
750
+ TryShowInterstitial();
751
+ }
752
+
753
+ // ❌ WRONG - Blocking user
754
+ public void OnLevelComplete()
755
+ {
756
+ if (interstitialAd.IsAdReady())
757
+ {
758
+ interstitialAd.ShowAd();
759
+ // Don't wait here to load next level!
760
+ }
761
+ }
762
+ ```
763
+
764
+ ### Error Handling
765
+
766
+ **Handle ad load failures:**
767
+ ```csharp
768
+ private void OnAdLoadFailed(LevelPlayAdError error)
769
+ {
770
+ Debug.LogWarning($"Ad load failed: {error.ErrorMessage}");
771
+
772
+ // Retry loading after a delay
773
+ Invoke(nameof(RetryLoad), 30f);
774
+ }
775
+
776
+ private void RetryLoad()
777
+ {
778
+ interstitialAd.LoadAd();
779
+ }
780
+ ```
781
+
782
+ ### Memory Management
783
+
784
+ **Always unsubscribe from events:**
785
+ ```csharp
786
+ void OnDestroy()
787
+ {
788
+ if (interstitialAd != null)
789
+ {
790
+ interstitialAd.OnAdLoaded -= OnAdLoaded;
791
+ interstitialAd.OnAdLoadFailed -= OnAdLoadFailed;
792
+ interstitialAd.OnAdDisplayed -= OnAdDisplayed;
793
+ interstitialAd.OnAdDisplayFailed -= OnAdDisplayFailed;
794
+ interstitialAd.OnAdClicked -= OnAdClicked;
795
+ interstitialAd.OnAdClosed -= OnAdClosed;
796
+ interstitialAd.OnAdInfoChanged -= OnAdInfoChanged;
797
+
798
+ // Destroy the ad to free its native resources
799
+ interstitialAd.DestroyAd();
800
+ }
801
+ }
802
+ ```
803
+
804
+ ## Common Issues
805
+
806
+ ### Issue: Error 1037 (Load during load)
807
+
808
+ **Cause:** Calling `LoadAd()` repeatedly in `Update()` or other high-frequency loops before the previous load completes.
809
+
810
+ **Common mistake:**
811
+ ```csharp
812
+ void Update()
813
+ {
814
+ // WRONG - This will cause error 1037!
815
+ if (!interstitialAd.IsAdReady())
816
+ {
817
+ interstitialAd.LoadAd();
818
+ }
819
+ }
820
+ ```
821
+
822
+ **Why this fails:** If the ad is still loading, calling `LoadAd()` again triggers error 1037: "Cannot load an interstitial while another interstitial is loading."
823
+
824
+ **Solution:** Track load state manually and only call `LoadAd()` once:
825
+ ```csharp
826
+ private bool isLoadingAd = false;
827
+
828
+ void Start()
829
+ {
830
+ LoadInterstitialAd();
831
+ }
832
+
833
+ void LoadInterstitialAd()
834
+ {
835
+ if (isLoadingAd) return; // Prevent duplicate loads
836
+
837
+ isLoadingAd = true;
838
+ interstitialAd.LoadAd();
839
+ }
840
+
841
+ void OnAdLoaded(LevelPlayAdInfo adInfo)
842
+ {
843
+ isLoadingAd = false;
844
+ }
845
+
846
+ void OnAdLoadFailed(LevelPlayAdError error)
847
+ {
848
+ isLoadingAd = false;
849
+ // Optionally retry after delay
850
+ }
851
+ ```
852
+
853
+ ### Issue: Interstitial showing too frequently
854
+
855
+ **Solution:** Implement frequency capping based on time or session count. Track when the last ad was shown and enforce a minimum interval.
856
+
857
+ ### Issue: User flow blocked by ad loading
858
+
859
+ **Solution:** Never wait for ads to load or show before progressing the user. Load ads proactively and show them opportunistically.
860
+
861
+ ### Issue: Ad not loading
862
+
863
+ **Possible causes:**
864
+ - SDK not initialized before creating ad object
865
+ - No internet connection
866
+ - Ad inventory not available
867
+ - Incorrect ad unit ID
868
+
869
+ **Solutions:**
870
+ - Create ad object only after `OnInitSuccess` callback
871
+ - Check network connectivity
872
+ - Verify ad unit ID in LevelPlay dashboard
873
+ - Test on real device with good connection
874
+
875
+ ### Issue: Ad loading but not showing
876
+
877
+ **Possible causes:**
878
+ - Not checking `IsAdReady()` before calling `ShowAd()`
879
+ - Ad expired (loaded too long ago)
880
+
881
+ **Solutions:**
882
+ - Always check `IsAdReady()` before showing
883
+ - Load ads close to when they'll be shown (within a few minutes)
884
+
885
+ ## Testing Checklist
886
+
887
+ - [ ] Ad loads successfully after SDK initialization
888
+ - [ ] `IsAdReady()` returns true when ad is loaded
889
+ - [ ] Ad displays correctly when `ShowAd()` is called
890
+ - [ ] Ad shows at appropriate transition points only
891
+ - [ ] Frequency capping works as expected
892
+ - [ ] User can progress regardless of ad status
893
+ - [ ] Ad reloads automatically after being shown
894
+ - [ ] Retry logic works when ad fails to load
895
+ - [ ] Multiple placements track correctly (if using)
896
+ - [ ] Placement capping works (if configured)
897
+ - [ ] Memory leaks prevented (events unsubscribed)
898
+ - [ ] Tested on multiple devices and network conditions
899
+ - [ ] Ad doesn't interrupt active gameplay