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.
- package/.claude/agents/nccgs-accessibility-specialist.md +26 -0
- package/.claude/agents/nccgs-adversarial-reviewer.md +26 -0
- package/.claude/agents/nccgs-ai-programmer.md +26 -0
- package/.claude/agents/nccgs-analytics-engineer.md +26 -0
- package/.claude/agents/nccgs-art-direction-lead.md +26 -0
- package/.claude/agents/nccgs-audio-direction-lead.md +26 -0
- package/.claude/agents/nccgs-creative-director.md +26 -0
- package/.claude/agents/nccgs-documentation-manager.md +26 -0
- package/.claude/agents/nccgs-economy-designer.md +26 -0
- package/.claude/agents/nccgs-engine-programmer.md +26 -0
- package/.claude/agents/nccgs-game-design-lead.md +26 -0
- package/.claude/agents/nccgs-game-designer.md +26 -0
- package/.claude/agents/nccgs-gameplay-programmer.md +26 -0
- package/.claude/agents/nccgs-level-designer.md +26 -0
- package/.claude/agents/nccgs-live-ops-designer.md +26 -0
- package/.claude/agents/nccgs-localization-lead.md +26 -0
- package/.claude/agents/nccgs-narrative-lead.md +26 -0
- package/.claude/agents/nccgs-network-programmer.md +26 -0
- package/.claude/agents/nccgs-performance-analyst.md +26 -0
- package/.claude/agents/nccgs-producer.md +26 -0
- package/.claude/agents/nccgs-production-coordinator.md +23 -0
- package/.claude/agents/nccgs-programming-lead.md +26 -0
- package/.claude/agents/nccgs-prototyper.md +26 -0
- package/.claude/agents/nccgs-qa-engineer.md +26 -0
- package/.claude/agents/nccgs-qa-lead.md +26 -0
- package/.claude/agents/nccgs-release-engineer.md +26 -0
- package/.claude/agents/nccgs-release-lead.md +26 -0
- package/.claude/agents/nccgs-security-engineer.md +26 -0
- package/.claude/agents/nccgs-sound-designer.md +26 -0
- package/.claude/agents/nccgs-systems-designer.md +26 -0
- package/.claude/agents/nccgs-technical-architect.md +26 -0
- package/.claude/agents/nccgs-technical-artist.md +26 -0
- package/.claude/agents/nccgs-technical-director.md +26 -0
- package/.claude/agents/nccgs-tools-programmer.md +26 -0
- package/.claude/agents/nccgs-ui-programmer.md +26 -0
- package/.claude/agents/nccgs-unity-build-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-content-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-implementer.md +26 -0
- package/.claude/agents/nccgs-unity-rendering-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-systems-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-ui-specialist.md +26 -0
- package/.claude/agents/nccgs-ux-designer.md +26 -0
- package/.claude/agents/nccgs-verification-engineer.md +26 -0
- package/.claude/agents/nccgs-world-builder.md +26 -0
- package/.claude/agents/nccgs-writer.md +26 -0
- package/.claude/nccgs/THIRD_PARTY_NOTICES.md +13 -0
- package/.claude/nccgs/VERSION +1 -0
- package/.claude/nccgs/constitution.md +131 -0
- package/.claude/nccgs/hooks/agent-audit.mjs +10 -0
- package/.claude/nccgs/hooks/common.mjs +41 -0
- package/.claude/nccgs/hooks/post-compact.mjs +1 -0
- package/.claude/nccgs/hooks/pre-compact.mjs +8 -0
- package/.claude/nccgs/hooks/protect-git.mjs +22 -0
- package/.claude/nccgs/hooks/protect-write.mjs +17 -0
- package/.claude/nccgs/hooks/session-start.mjs +15 -0
- package/.claude/nccgs/hooks/session-stop.mjs +7 -0
- package/.claude/nccgs/protocols/agent-contract.md +34 -0
- package/.claude/nccgs/protocols/context-packets.md +13 -0
- package/.claude/nccgs/protocols/evidence.md +15 -0
- package/.claude/nccgs/protocols/model-routing.md +22 -0
- package/.claude/nccgs/protocols/orchestration.md +26 -0
- package/.claude/nccgs/protocols/unity-boundary.md +11 -0
- package/.claude/nccgs/settings.fragment.json +77 -0
- package/.claude/nccgs/studio.json +347 -0
- package/.claude/nccgs/tools/configure-models.mjs +39 -0
- package/.claude/nccgs/unity-skills-manifest.json +727 -0
- package/.claude/nccgs/workflow-catalog.json +317 -0
- package/.claude/rules/nccgs-canonical-docs.md +19 -0
- package/.claude/rules/nccgs-editor-tools.md +12 -0
- package/.claude/rules/nccgs-localization.md +12 -0
- package/.claude/rules/nccgs-networking.md +13 -0
- package/.claude/rules/nccgs-performance.md +14 -0
- package/.claude/rules/nccgs-rendering.md +16 -0
- package/.claude/rules/nccgs-security.md +13 -0
- package/.claude/rules/nccgs-tests.md +18 -0
- package/.claude/rules/nccgs-ui.md +14 -0
- package/.claude/rules/nccgs-unity-assets.md +21 -0
- package/.claude/rules/nccgs-unity-code.md +22 -0
- package/.claude/skills/accessibility-review/SKILL.md +14 -0
- package/.claude/skills/architecture-decision/SKILL.md +14 -0
- package/.claude/skills/asset-audit/SKILL.md +14 -0
- package/.claude/skills/audit/SKILL.md +16 -0
- package/.claude/skills/audit/references/dimensions.md +46 -0
- package/.claude/skills/balance-review/SKILL.md +14 -0
- package/.claude/skills/bug-triage/SKILL.md +14 -0
- package/.claude/skills/build-live-game/SKILL.md +317 -0
- package/.claude/skills/build-live-game/references/achievements.md +779 -0
- package/.claude/skills/build-live-game/references/apis.md +280 -0
- package/.claude/skills/build-live-game/references/authentication.md +437 -0
- package/.claude/skills/build-live-game/references/battlepass.md +860 -0
- package/.claude/skills/build-live-game/references/cloud-code.md +563 -0
- package/.claude/skills/build-live-game/references/cloud-save.md +474 -0
- package/.claude/skills/build-live-game/references/deployment.md +216 -0
- package/.claude/skills/build-live-game/references/player-account.md +813 -0
- package/.claude/skills/build-live-game/references/remote-config.md +96 -0
- package/.claude/skills/build-live-game/references/tooling.md +431 -0
- package/.claude/skills/closure/SKILL.md +14 -0
- package/.claude/skills/code-review/SKILL.md +14 -0
- package/.claude/skills/compatibility-review/SKILL.md +14 -0
- package/.claude/skills/context-pack/SKILL.md +14 -0
- package/.claude/skills/dependency-review/SKILL.md +14 -0
- package/.claude/skills/design/SKILL.md +20 -0
- package/.claude/skills/design-review/SKILL.md +14 -0
- package/.claude/skills/evidence-review/SKILL.md +14 -0
- package/.claude/skills/hotfix/SKILL.md +14 -0
- package/.claude/skills/implement-in-app-purchases/README.md +233 -0
- package/.claude/skills/implement-in-app-purchases/SKILL.md +158 -0
- package/.claude/skills/implement-in-app-purchases/references/api-notes.md +562 -0
- package/.claude/skills/implement-in-app-purchases/references/codeless-catalog.md +331 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-adapty.md +268 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-revenuecat.md +275 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
- package/.claude/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +204 -0
- package/.claude/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +198 -0
- package/.claude/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +356 -0
- package/.claude/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +446 -0
- package/.claude/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +680 -0
- package/.claude/skills/implement-in-app-purchases/references/platform-notes.md +204 -0
- package/.claude/skills/implement-in-app-purchases/references/pre-check.md +205 -0
- package/.claude/skills/incident-recovery/SKILL.md +14 -0
- package/.claude/skills/initialize-ai-navigation/SKILL.md +95 -0
- package/.claude/skills/initialize-ai-navigation/references/navigation-system.md +794 -0
- package/.claude/skills/levelplay-unity-integration/CHANGELOG.md +57 -0
- package/.claude/skills/levelplay-unity-integration/README.md +74 -0
- package/.claude/skills/levelplay-unity-integration/SKILL.md +1126 -0
- package/.claude/skills/levelplay-unity-integration/references/banner-api.md +920 -0
- package/.claude/skills/levelplay-unity-integration/references/best-practices.md +536 -0
- package/.claude/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
- package/.claude/skills/levelplay-unity-integration/references/initialization-api.md +630 -0
- package/.claude/skills/levelplay-unity-integration/references/interstitial-api.md +899 -0
- package/.claude/skills/levelplay-unity-integration/references/ios-setup.md +491 -0
- package/.claude/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
- package/.claude/skills/levelplay-unity-integration/references/privacy-settings.md +608 -0
- package/.claude/skills/levelplay-unity-integration/references/rewarded-api.md +902 -0
- package/.claude/skills/localization/SKILL.md +135 -0
- package/.claude/skills/localization/references/api-notes.md +76 -0
- package/.claude/skills/localization/resources/L10nBatchProcessor.cs +69 -0
- package/.claude/skills/localization/resources/LocalizedFontAsset.cs +18 -0
- package/.claude/skills/localize-game/SKILL.md +14 -0
- package/.claude/skills/migrate-project/SKILL.md +21 -0
- package/.claude/skills/migrate-project/references/procedure.md +63 -0
- package/.claude/skills/milestone-review/SKILL.md +14 -0
- package/.claude/skills/new-unity-project/SKILL.md +179 -0
- package/.claude/skills/optimize-audio/SKILL.md +199 -0
- package/.claude/skills/optimize-audio/resources/audio-import-api.md +146 -0
- package/.claude/skills/optimize-audio/resources/platform-settings.md +48 -0
- package/.claude/skills/optimize-text-mesh-pro/SKILL.md +182 -0
- package/.claude/skills/optimize-web/SKILL.md +393 -0
- package/.claude/skills/optimize-web/resources/WebOptimizer.cs +21 -0
- package/.claude/skills/optimize-web/resources/toktx-examples.sh +11 -0
- package/.claude/skills/performance-audit/SKILL.md +14 -0
- package/.claude/skills/physics-3d-collision/SKILL.md +442 -0
- package/.claude/skills/physics-3d-collision/references/troubleshooting.md +41 -0
- package/.claude/skills/physics-3d-collision/resources/CollisionDebugger.cs +33 -0
- package/.claude/skills/plan-feature/SKILL.md +14 -0
- package/.claude/skills/playtest/SKILL.md +14 -0
- package/.claude/skills/project-stage/SKILL.md +14 -0
- package/.claude/skills/prototype-feature/SKILL.md +14 -0
- package/.claude/skills/qa-plan/SKILL.md +14 -0
- package/.claude/skills/release/SKILL.md +18 -0
- package/.claude/skills/release-readiness/SKILL.md +14 -0
- package/.claude/skills/retrospective/SKILL.md +14 -0
- package/.claude/skills/review/SKILL.md +16 -0
- package/.claude/skills/security-audit/SKILL.md +14 -0
- package/.claude/skills/setup-multiplayer-services/SKILL.md +39 -0
- package/.claude/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
- package/.claude/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
- package/.claude/skills/setup-multiplayer-services/references/examples.md +33 -0
- package/.claude/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
- package/.claude/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
- package/.claude/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
- package/.claude/skills/setup-vivox-voice-chat/SKILL.md +118 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/.env.example +6 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/README.md +101 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/promptfooconfig.yaml +32 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/init-and-login.yaml +76 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/text-chat.yaml +65 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/voice-channels.yaml +74 -0
- package/.claude/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
- package/.claude/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
- package/.claude/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
- package/.claude/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
- package/.claude/skills/setup-vivox-voice-chat/references/voice-channels.md +90 -0
- package/.claude/skills/shader-graph-create-custom-node/SKILL.md +25 -0
- package/.claude/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
- package/.claude/skills/sprint-plan/SKILL.md +14 -0
- package/.claude/skills/sprite-editor/SKILL.md +66 -0
- package/.claude/skills/sprite-editor/references/api_reference.md +151 -0
- package/.claude/skills/sprite-editor/references/background.md +112 -0
- package/.claude/skills/sprite-editor/references/templates.md +72 -0
- package/.claude/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
- package/.claude/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
- package/.claude/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
- package/.claude/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
- package/.claude/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
- package/.claude/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
- package/.claude/skills/sprite-editor/scripts/README.md +134 -0
- package/.claude/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
- package/.claude/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
- package/.claude/skills/status/SKILL.md +16 -0
- package/.claude/skills/story-readiness/SKILL.md +14 -0
- package/.claude/skills/test/SKILL.md +16 -0
- package/.claude/skills/ui/SKILL.md +142 -0
- package/.claude/skills/ui-imgui/SKILL.md +186 -0
- package/.claude/skills/ui-imgui/references/gui-elements.md +156 -0
- package/.claude/skills/ui-imgui/references/templates.md +141 -0
- package/.claude/skills/ui-review/SKILL.md +14 -0
- package/.claude/skills/ui-ugui/SKILL.md +282 -0
- package/.claude/skills/ui-ugui/references/scrollview-setup.md +29 -0
- package/.claude/skills/ui-uitk/SKILL.md +235 -0
- package/.claude/skills/ui-uitk/references/common-issues.md +74 -0
- package/.claude/skills/ui-uitk/references/custom-elements.md +241 -0
- package/.claude/skills/ui-uitk/references/painter2d.md +282 -0
- package/.claude/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
- package/.claude/skills/ui-uitk/references/svg-icons.md +136 -0
- package/.claude/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
- package/.claude/skills/ui-uitk/references/uss-guide.md +138 -0
- package/.claude/skills/unity-cli/CHANGELOG.md +233 -0
- package/.claude/skills/unity-cli/SECURITY.md +22 -0
- package/.claude/skills/unity-cli/SKILL.md +414 -0
- package/.claude/skills/unity-cli/references/auth-license-cloud.md +146 -0
- package/.claude/skills/unity-cli/references/build-run-test.md +349 -0
- package/.claude/skills/unity-cli/references/collaboration.md +472 -0
- package/.claude/skills/unity-cli/references/config-hub.md +103 -0
- package/.claude/skills/unity-cli/references/diagnostics-maintenance.md +326 -0
- package/.claude/skills/unity-cli/references/editors-install.md +327 -0
- package/.claude/skills/unity-cli/references/integration-advanced.md +472 -0
- package/.claude/skills/unity-cli/references/projects-templates.md +574 -0
- package/.claude/skills/unity-package-management/SKILL.md +304 -0
- package/.claude/skills/unity-package-management/references/select-packages.md +108 -0
- package/.claude/skills/urp-postprocessing/SKILL.md +188 -0
- package/.claude/skills/urp-postprocessing/references/code-templates.md +119 -0
- package/.claude/skills/urp-postprocessing/references/effect-reference.md +86 -0
- package/.claude/skills/validate-urp-render-graph-renderer-feature/SKILL.md +269 -0
- package/.claude/skills/work/SKILL.md +36 -0
- package/.claude/skills/work/references/classification.md +41 -0
- package/.claude/skills/work/references/closure.md +50 -0
- package/.claude/skills/work/references/feature-contracts.md +32 -0
- package/.claude/skills/work/references/verification.md +26 -0
- package/CLAUDE.md +6 -0
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/THIRD_PARTY_NOTICES.md +23 -0
- package/UPGRADING.md +32 -0
- package/VERSION +1 -0
- package/docs/ARCHITECTURE.md +73 -0
- package/docs/HUONG-DAN-MIGRATE-VA-SU-DUNG.md +324 -0
- package/docs/MIGRATION-MATRIX.md +23 -0
- package/docs/PROJECT-POLICY.md +67 -0
- package/docs/WORKFLOWS.md +61 -0
- package/package-assets/setup-vivox-voice-chat-evals.gitignore +7 -0
- package/package.json +41 -0
- package/scaffold/.nccgs/bugs/.gitkeep +1 -0
- package/scaffold/.nccgs/closures/.gitkeep +1 -0
- package/scaffold/.nccgs/context/.gitkeep +1 -0
- package/scaffold/.nccgs/decisions/.gitkeep +1 -0
- package/scaffold/.nccgs/evidence/.gitkeep +1 -0
- package/scaffold/.nccgs/features/.gitkeep +1 -0
- package/scaffold/.nccgs/migrations/.gitkeep +1 -0
- package/scaffold/.nccgs/playtests/.gitkeep +1 -0
- package/scaffold/.nccgs/project.yaml +103 -0
- package/scaffold/.nccgs/requirements.yaml +10 -0
- package/scaffold/.nccgs/reviews/.gitkeep +1 -0
- package/scaffold/.nccgs/state.md +40 -0
- package/scaffold/.nccgs/templates/agent-handoff.md +25 -0
- package/scaffold/.nccgs/templates/architecture-decision.md +27 -0
- package/scaffold/.nccgs/templates/closure-record.md +51 -0
- package/scaffold/.nccgs/templates/context-packet.yaml +17 -0
- package/scaffold/.nccgs/templates/evidence-record.md +23 -0
- package/scaffold/.nccgs/templates/feature-contract.md +35 -0
- package/scaffold/.nccgs/templates/migration-plan.md +40 -0
- package/scaffold/.nccgs/templates/waiver.md +11 -0
- package/scripts/cli.mjs +56 -0
- package/scripts/install.mjs +267 -0
- package/scripts/sync-unity-skills.mjs +126 -0
- package/scripts/validate.mjs +205 -0
- package/tests/framework.test.mjs +121 -0
package/.claude/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Convert Native Google Billing to Unity IAP 5
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Trigger Phrases](#trigger-phrases)
|
|
6
|
+
- [Important Constraints](#important-constraints)
|
|
7
|
+
- [Step 1 — Pre-Conversion Scan](#step-1--pre-conversion-scan)
|
|
8
|
+
- [Step 2 — Product Classification](#step-2--product-classification)
|
|
9
|
+
- [Step 3 — Migration Report (produce before any edits)](#step-3--migration-report-produce-before-any-edits)
|
|
10
|
+
- [Step 4 — Blocker Detection](#step-4--blocker-detection)
|
|
11
|
+
- [Step 5 — Target Architecture](#step-5--target-architecture)
|
|
12
|
+
- [Step 6 — Migration Phases](#step-6--migration-phases)
|
|
13
|
+
- [Step 7 — Behavior Change Rules](#step-7--behavior-change-rules)
|
|
14
|
+
- [Step 8 — Native → Unity IAP Concept Mapping](#step-8--native--unity-iap-concept-mapping)
|
|
15
|
+
- [Step 9 — Rollback Plan](#step-9--rollback-plan)
|
|
16
|
+
- [Step 10 — Test Checklist](#step-10--test-checklist)
|
|
17
|
+
- [Step 11 — Questions to Ask (only when required)](#step-11--questions-to-ask-only-when-required)
|
|
18
|
+
|
|
19
|
+
Use this reference when the project uses C# → Java/Kotlin AndroidJavaObject calls to Google Play BillingClient and needs to be migrated to `com.unity.purchasing`. Always install the latest stable version.
|
|
20
|
+
|
|
21
|
+
## Trigger Phrases
|
|
22
|
+
|
|
23
|
+
- "Convert native Google Billing to the latest Unity IAP"
|
|
24
|
+
- "Migrate BillingClient integration to Unity IAP"
|
|
25
|
+
- "Replace AndroidJavaObject Google billing bridge with Unity IAP"
|
|
26
|
+
- "Upgrade custom Google Play Billing to the latest stable version of com.unity.purchasing"
|
|
27
|
+
- "Remove native BillingClient and use Unity IAP"
|
|
28
|
+
|
|
29
|
+
## Important Constraints
|
|
30
|
+
|
|
31
|
+
- **Do not delete existing native billing files unless explicitly requested.** Always preserve with `#if !USE_UNITY_IAP_V5` guards.
|
|
32
|
+
- **Create the new Unity IAP adapter first**, then mark the old native adapter as deprecated.
|
|
33
|
+
- **Preserve public game-facing APIs** via a compatibility facade so gameplay code does not need large rewrites.
|
|
34
|
+
- **Do not change product IDs.**
|
|
35
|
+
- **Do not change backend validation endpoints** unless the receipt format change makes it unavoidable — document any backend change required.
|
|
36
|
+
- **Do not grant purchases on the client** if the existing project uses server-side validation.
|
|
37
|
+
- **Do not assume all products are consumables.** Detect and classify each product.
|
|
38
|
+
- **Do not assume subscriptions are simple.** Detect base plans, offer tokens, pricing phases, and `SubscriptionOfferDetails`. If found, surface as a migration blocker and let the user choose a path (see Subscription Blocker Options below).
|
|
39
|
+
- **If the project contains RevenueCat, Adapty, or Essential Kit**, stop and notify the user — this skill does not support converting those packages.
|
|
40
|
+
- **If Google-specific features are not cleanly expressible in Unity IAP**, report them as migration blockers rather than silently removing them.
|
|
41
|
+
|
|
42
|
+
## Step 1 — Pre-Conversion Scan
|
|
43
|
+
|
|
44
|
+
Scan before making any changes. Do not edit files until the migration report is accepted.
|
|
45
|
+
|
|
46
|
+
### 1a — Unity C# Bridge Patterns
|
|
47
|
+
|
|
48
|
+
Search `Assets/**/*.cs`:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
AndroidJavaObject|AndroidJavaClass|UnityPlayer\.currentActivity
|
|
52
|
+
UnitySendMessage
|
|
53
|
+
GoogleBilling|BillingManager|BillingClient|BillingBridge|AndroidBillingBridge|PlayBilling
|
|
54
|
+
purchaseToken|originalJson|signature|productId|orderId
|
|
55
|
+
\backnowledge\b|\bconsume\b
|
|
56
|
+
restore.?purchases|query.?products|query.?purchases
|
|
57
|
+
subscription.?status|receipt.?valid|entitlement.?grant
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 1b — Android Java/Kotlin Patterns
|
|
61
|
+
|
|
62
|
+
Search `Assets/Plugins/Android/**/*.java`, `*.kt`:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
com\.android\.billingclient\.api\.BillingClient
|
|
66
|
+
PurchasesUpdatedListener|BillingClientStateListener
|
|
67
|
+
ProductDetails|ProductDetails\.SubscriptionOfferDetails
|
|
68
|
+
QueryProductDetailsParams|BillingFlowParams
|
|
69
|
+
AcknowledgePurchaseParams|ConsumeParams|QueryPurchasesParams
|
|
70
|
+
launchBillingFlow|acknowledgePurchase|consumeAsync
|
|
71
|
+
queryProductDetailsAsync|queryPurchasesAsync|enablePendingPurchases
|
|
72
|
+
offerToken|basePlanId|offerId|pricingPhases
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 1c — Gradle / Manifest Patterns
|
|
76
|
+
|
|
77
|
+
Search `mainTemplate.gradle`, `launcherTemplate.gradle`, `baseProjectTemplate.gradle`, `AndroidManifest.xml`:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
com\.android\.billingclient:billing
|
|
81
|
+
com\.android\.billingclient:billing-ktx
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Also list all `.jar`/`.aar` files under `Assets/Plugins/Android/` — these may contain pre-compiled billing code.
|
|
85
|
+
|
|
86
|
+
### 1d — Scene / Prefab / Asset Scan
|
|
87
|
+
|
|
88
|
+
Search `.unity`, `.prefab`, `.asset` files for references to billing-related MonoBehaviour names found in 1a.
|
|
89
|
+
|
|
90
|
+
## Step 2 — Product Classification
|
|
91
|
+
|
|
92
|
+
Classify every detected product into one of: **Consumable**, **NonConsumable**, **Subscription**, **Unknown**.
|
|
93
|
+
|
|
94
|
+
Infer from (in priority order):
|
|
95
|
+
1. `BillingClient.ProductType.INAPP` (consumable or non-consumable) / `BillingClient.ProductType.SUBS`
|
|
96
|
+
2. `consumeAsync` calls → Consumable; `acknowledgePurchase` without consume → NonConsumable
|
|
97
|
+
3. Product ID naming conventions (e.g., `coins`, `gems`, `pack` → Consumable; `remove_ads`, `unlock` → NonConsumable; `monthly`, `annual`, `sub` → Subscription)
|
|
98
|
+
4. Entitlement / backend grant code
|
|
99
|
+
5. Comments or config files
|
|
100
|
+
|
|
101
|
+
If type cannot be confidently inferred, mark as **Unknown** and add to the blocker question list.
|
|
102
|
+
|
|
103
|
+
## Step 3 — Migration Report (produce before any edits)
|
|
104
|
+
|
|
105
|
+
Generate all 18 sections. Do not skip any.
|
|
106
|
+
|
|
107
|
+
1. **Current native billing architecture** — describe the bridge pattern (C# wrapper → JNI → BillingClient)
|
|
108
|
+
2. **Files using native Google Billing** — full list with role of each file
|
|
109
|
+
3. **Product catalog discovered** — all product IDs found
|
|
110
|
+
4. **Product type mapping** — inferred type + confidence + source of inference for each product
|
|
111
|
+
5. **Purchase flow mapping** — native → Unity IAP step-by-step
|
|
112
|
+
6. **Restore purchase flow mapping** — `queryPurchasesAsync` → `FetchPurchases` + `RestoreTransactions`
|
|
113
|
+
7. **Backend validation mapping** — what data the old flow sent (`purchaseToken`, `originalJson`, `signature`, `packageName`) vs what Unity IAP provides (`order.Info.Receipt`, `order.Info.Apple?.jwsRepresentation`)
|
|
114
|
+
8. **Consumable consume behavior mapping** — native `consumeAsync` → Unity IAP `ConfirmPurchase` (only after grant)
|
|
115
|
+
9. **Non-consumable acknowledgement behavior mapping** — native `acknowledgePurchase` → Unity IAP `ConfirmPurchase` (only after grant)
|
|
116
|
+
10. **Subscription behavior mapping** — detected subscription products, restore path, renewal handling
|
|
117
|
+
11. **Google-specific features detected** — list each (see Blocker Detection below)
|
|
118
|
+
12. **Unity IAP 5.2 migration blockers** — features that cannot be cleanly mapped
|
|
119
|
+
13. **Proposed new Unity IAP architecture** — new files and their roles
|
|
120
|
+
14. **Code files to create** — with paths
|
|
121
|
+
15. **Code files to modify** — with nature of each change
|
|
122
|
+
16. **Manual Play Console checks** — product IDs, base plan compatibility, billing permissions
|
|
123
|
+
17. **Test plan** — from the checklist in this document
|
|
124
|
+
18. **Rollback plan** — from the rollback plan section in this document
|
|
125
|
+
|
|
126
|
+
## Step 4 — Blocker Detection
|
|
127
|
+
|
|
128
|
+
Report these as migration blockers if detected. Do not silently remove them.
|
|
129
|
+
|
|
130
|
+
| Feature | Detection Signal | Blocker Level |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| Multiple subscription base plans | `basePlanId` usage, multiple `SubscriptionOfferDetails` per product | **Hard** — ask user to choose option A/B/C (see below) |
|
|
133
|
+
| Explicit offer token selection | `offerToken` set on `BillingFlowParams` | **Hard** |
|
|
134
|
+
| Introductory offer selection by `offerId` | `offerId` in offer params | **Hard** |
|
|
135
|
+
| Offer tags | `offerTags` access on `SubscriptionOfferDetails` | **Soft** — document loss |
|
|
136
|
+
| Pricing phase inspection | `pricingPhases` / `PricingPhase` fields read | **Soft** — document loss |
|
|
137
|
+
| Multi-quantity purchases | `quantity` > 1 in `BillingFlowParams` | **Hard** |
|
|
138
|
+
| Alternative billing / external offers | `setExternalOfferToken` or alternative billing config | **Hard** |
|
|
139
|
+
| Personalized price disclosure | `setIsPersonalizedPrice(true)` | **Hard** |
|
|
140
|
+
| Obfuscated account / profile IDs | `setObfuscatedAccountId`, `setObfuscatedProfileId` | **Soft** — Unity IAP exposes `SetObfuscatedAccountId/ProfileId` post-`Connect()` on `GooglePlayStoreExtendedService` |
|
|
141
|
+
| Custom `BillingFlowParams` fields | Any `BillingFlowParams.Builder` method not listed above | **Soft** — document loss |
|
|
142
|
+
| Direct `ProductDetails` metadata | Reading `ProductDetails` fields not available on `Product.metadata` | **Soft** — document loss |
|
|
143
|
+
|
|
144
|
+
### Subscription Blocker Options (present to user when hard subscription blockers found)
|
|
145
|
+
|
|
146
|
+
**A mixed Unity IAP + native BillingClient architecture is not recommended and must not be offered as an option.** Both systems compete for the same `PurchasesUpdatedListener` slot on the device — only one receives purchase callbacks, the other silently drops purchases. This risks lost purchases, double grants, and unacknowledged tokens. If the user asks about a mixed approach, explain this risk and redirect to Option A or B.
|
|
147
|
+
|
|
148
|
+
**Option A — Simplify Play Console setup for Unity IAP compatibility**
|
|
149
|
+
Remove extra base plans/offers in Play Console so one product has one base plan. Unity IAP then handles all products including subscriptions. This is the recommended path — single system, no coexistence risk.
|
|
150
|
+
|
|
151
|
+
**Option B — Stay on native Google Billing for all products**
|
|
152
|
+
Do not migrate at this time. Keep the native BillingClient implementation as-is until the Play Console subscription configuration can be simplified or Unity IAP exposes the required subscription features. Stop the conversion and document the blocker and this decision in `IapMigrationNotes.md`.
|
|
153
|
+
|
|
154
|
+
## Step 5 — Target Architecture
|
|
155
|
+
|
|
156
|
+
Create under `Assets/Scripts/IAP/`:
|
|
157
|
+
|
|
158
|
+
| File | Purpose |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `IStorePurchaseService.cs` | Game-facing interface (stable public API) |
|
|
161
|
+
| `UnityIapStorePurchaseService.cs` | Unity IAP 5.x implementation |
|
|
162
|
+
| `ProductCatalogDefinition.cs` | ScriptableObject or plain class holding all `ProductDefinitionEntry` |
|
|
163
|
+
| `ProductDefinitionEntry.cs` | Per-product data: ID, type, store-specific IDs |
|
|
164
|
+
| `PurchaseEntitlementMapper.cs` | Maps Unity IAP order data → game grant calls |
|
|
165
|
+
| `PurchaseValidationRequest.cs` | DTO sent to backend |
|
|
166
|
+
| `PurchaseValidationResult.cs` | DTO received from backend |
|
|
167
|
+
| `PurchaseRestoreResult.cs` | Result of restore operation |
|
|
168
|
+
| `LegacyGoogleBillingAdapterDeprecated.cs` | Compatibility facade (only if game code calls old billing API) |
|
|
169
|
+
| `IapMigrationNotes.md` | Human-readable notes on what changed, blockers found, manual steps |
|
|
170
|
+
|
|
171
|
+
### Game-Facing Interface (preserve or adapt from existing API surface)
|
|
172
|
+
|
|
173
|
+
```csharp
|
|
174
|
+
public interface IStorePurchaseService
|
|
175
|
+
{
|
|
176
|
+
Task InitializeAsync();
|
|
177
|
+
Task FetchProductsAsync();
|
|
178
|
+
IReadOnlyList<StoreProductInfo> GetProducts();
|
|
179
|
+
Task PurchaseAsync(string productId);
|
|
180
|
+
Task RestorePurchasesAsync();
|
|
181
|
+
bool IsInitialized { get; }
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Step 6 — Migration Phases
|
|
186
|
+
|
|
187
|
+
### Phase 1 — Package Check
|
|
188
|
+
|
|
189
|
+
- Verify `com.unity.purchasing` exists in `Packages/manifest.json`.
|
|
190
|
+
- If `com.unity.purchasing` is absent or outdated, install the latest stable version via Package Manager.
|
|
191
|
+
- If missing or outdated, provide Package Manager instructions. Do not auto-edit `manifest.json` unless the user explicitly allows it.
|
|
192
|
+
|
|
193
|
+
### Phase 2 — Product Catalog Extraction
|
|
194
|
+
|
|
195
|
+
- Extract all product IDs and inferred types from the scan.
|
|
196
|
+
- Generate `ProductCatalogDefinition.cs` / `ProductDefinitionEntry.cs`.
|
|
197
|
+
- Each entry: `productId`, `ProductType`, optional `storeSpecificIds`, `notes`.
|
|
198
|
+
|
|
199
|
+
### Phase 3 — New Unity IAP Service
|
|
200
|
+
|
|
201
|
+
Create `UnityIapStorePurchaseService`:
|
|
202
|
+
|
|
203
|
+
1. **Initialization** — `UnityIAPServices.StoreController()`, subscribe all events **before** `Connect()`.
|
|
204
|
+
2. **Product fetching** — build `List<ProductDefinition>` from catalog, call `store.FetchProducts()`, handle `OnProductsFetched` / `OnProductsFetchFailed`.
|
|
205
|
+
3. **Purchase initiation** — `store.PurchaseProduct(product)`.
|
|
206
|
+
4. **Purchase callback** — `OnPurchasePending`: validate receipt → grant entitlement → `ConfirmPurchase(pendingOrder)`. **Never confirm before grant.**
|
|
207
|
+
5. **Deferred purchases** — `OnPurchaseDeferred`: show pending UI, do not grant.
|
|
208
|
+
6. **Failed purchases** — `OnPurchaseFailed`: map `FailureReason` to user-facing error.
|
|
209
|
+
7. **Restore / fetch** — `store.FetchPurchases()` (re-delivers unconfirmed via `OnPurchasePending`) + `store.RestoreTransactions(callback)` for explicit iOS restore button.
|
|
210
|
+
8. **Validation handoff** — send `order.Info.Receipt` (and `order.Info.Apple?.jwsRepresentation` on Apple) to backend in place of legacy `purchaseToken` + `originalJson` + `signature`. Document any backend change required.
|
|
211
|
+
|
|
212
|
+
### Phase 4 — Compatibility Facade
|
|
213
|
+
|
|
214
|
+
If game code calls the old billing API directly (e.g., `GoogleBillingManager.Purchase(id)`):
|
|
215
|
+
|
|
216
|
+
- Create `LegacyGoogleBillingAdapterDeprecated.cs` that implements the same method signatures.
|
|
217
|
+
- Delegate all calls to `UnityIapStorePurchaseService`.
|
|
218
|
+
- Mark all methods `[Obsolete("Use IStorePurchaseService — remove after migration validation")]`.
|
|
219
|
+
|
|
220
|
+
### Phase 5 — Remove Native Dependency from Active Path
|
|
221
|
+
|
|
222
|
+
- Stop calling `AndroidJavaObject` bridge for migrated products.
|
|
223
|
+
- Wrap native calls in `#if !USE_UNITY_IAP_V5` — do not delete them.
|
|
224
|
+
- Leave Gradle billing dependencies unless user explicitly requests removal.
|
|
225
|
+
|
|
226
|
+
### Phase 6 — Test Scaffolding
|
|
227
|
+
|
|
228
|
+
- Add debug logs at each IAP event.
|
|
229
|
+
- Add editor stubs for sandbox testing.
|
|
230
|
+
- Add the QA checklist from the test plan below to `IapMigrationNotes.md`.
|
|
231
|
+
|
|
232
|
+
## Step 7 — Behavior Change Rules
|
|
233
|
+
|
|
234
|
+
### Acknowledgement and Consumption
|
|
235
|
+
|
|
236
|
+
Native billing requires explicit `acknowledgePurchase` or `consumeAsync`. Unity IAP abstracts both through `ConfirmPurchase(pendingOrder)`. Map:
|
|
237
|
+
|
|
238
|
+
| Native | Unity IAP |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `consumeAsync` (consumable) | `ConfirmPurchase(pendingOrder)` after grant |
|
|
241
|
+
| `acknowledgePurchase` (non-consumable / subscription) | `ConfirmPurchase(pendingOrder)` after grant |
|
|
242
|
+
|
|
243
|
+
**Never call `ConfirmPurchase` before the entitlement is safely granted.**
|
|
244
|
+
|
|
245
|
+
### Backend Validation
|
|
246
|
+
|
|
247
|
+
| Native field sent | Unity IAP equivalent |
|
|
248
|
+
|---|---|
|
|
249
|
+
| `purchaseToken` | `order.Info.Receipt` (contains the Google receipt JSON) |
|
|
250
|
+
| `originalJson` | Embedded in `order.Info.Receipt` |
|
|
251
|
+
| `signature` | Embedded in `order.Info.Receipt` |
|
|
252
|
+
| `packageName` | `Application.identifier` |
|
|
253
|
+
| `productId` | `pendingOrder.CartOrdered.Items().First().Product.definition.id` |
|
|
254
|
+
|
|
255
|
+
If the backend parses `purchaseToken` or `originalJson` fields directly, document the receipt format change as a required backend update.
|
|
256
|
+
|
|
257
|
+
### Obfuscated IDs
|
|
258
|
+
|
|
259
|
+
If native code sets `setObfuscatedAccountId` / `setObfuscatedProfileId` in `BillingFlowParams`, set the equivalent **after** `await store.Connect()`:
|
|
260
|
+
|
|
261
|
+
```csharp
|
|
262
|
+
store.GooglePlayStoreExtendedService?.SetObfuscatedAccountId("hashed_id");
|
|
263
|
+
store.GooglePlayStoreExtendedService?.SetObfuscatedProfileId("hashed_profile_id");
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Retrieve per-order:
|
|
267
|
+
|
|
268
|
+
```csharp
|
|
269
|
+
string accountId = store.GooglePlayStoreExtendedPurchaseService?.GetObfuscatedAccountId(order);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Pending Purchases
|
|
273
|
+
|
|
274
|
+
If native code handles `BillingClient.enablePendingPurchases()` or checks purchase state for `PENDING`:
|
|
275
|
+
|
|
276
|
+
- Unity IAP surfaces deferred purchases via `store.OnPurchaseDeferred`.
|
|
277
|
+
- On `OnPurchaseDeferred`: show "pending approval" UI. Do not grant.
|
|
278
|
+
- When approved, the store re-delivers via `store.OnPurchasePending`.
|
|
279
|
+
|
|
280
|
+
### Subscription Upgrade / Downgrade
|
|
281
|
+
|
|
282
|
+
If native code calls `launchBillingFlow` with a `subscriptionUpdateParams` (prorating an existing subscription):
|
|
283
|
+
|
|
284
|
+
```csharp
|
|
285
|
+
store.GooglePlayStoreExtendedPurchaseService?.UpgradeDowngradeSubscription(
|
|
286
|
+
currentOrder, // Order object of the current subscription
|
|
287
|
+
newProduct, // Product to upgrade/downgrade to
|
|
288
|
+
GooglePlayReplacementMode.ChargeFullPrice // choose appropriate mode
|
|
289
|
+
);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
See [platform-notes.md](platform-notes.md) for all `GooglePlayReplacementMode` values.
|
|
293
|
+
|
|
294
|
+
## Step 8 — Native → Unity IAP Concept Mapping
|
|
295
|
+
|
|
296
|
+
| Native Google Billing | Unity IAP 5.x |
|
|
297
|
+
|---|---|
|
|
298
|
+
| `ProductDetails` | `Product` (via `store.GetProductById`) |
|
|
299
|
+
| `Purchase` | `PendingOrder` (on `OnPurchasePending`) |
|
|
300
|
+
| `purchaseToken` | `order.Info.Receipt` (contains the token) |
|
|
301
|
+
| `originalJson` | embedded in `order.Info.Receipt` |
|
|
302
|
+
| `signature` | embedded in `order.Info.Receipt` |
|
|
303
|
+
| `acknowledgePurchase` | `store.ConfirmPurchase(pendingOrder)` |
|
|
304
|
+
| `consumeAsync` | `store.ConfirmPurchase(pendingOrder)` |
|
|
305
|
+
| `queryPurchasesAsync` | `store.FetchPurchases()` → `OnPurchasesFetched` |
|
|
306
|
+
| `BillingResult` / `BillingResponseCode` | `FailedOrder.FailureReason` / `StoreConnectionFailureDescription` |
|
|
307
|
+
| `ProductType.INAPP` | `ProductType.Consumable` or `ProductType.NonConsumable` (distinguish by consume behavior) |
|
|
308
|
+
| `ProductType.SUBS` | `ProductType.Subscription` |
|
|
309
|
+
| `offerToken` / `basePlanId` / `pricingPhases` | **Not directly exposed** — report as blocker |
|
|
310
|
+
|
|
311
|
+
## Step 9 — Rollback Plan
|
|
312
|
+
|
|
313
|
+
- Wrap all new IAP code in `#if USE_UNITY_IAP_V5`.
|
|
314
|
+
- Wrap all replaced native bridge calls in `#if !USE_UNITY_IAP_V5`.
|
|
315
|
+
- To revert: remove `USE_UNITY_IAP_V5` from **Edit > Project Settings > Player > Scripting Define Symbols**. The native billing path is restored without any code changes.
|
|
316
|
+
- Never activate both purchase systems for the same product simultaneously.
|
|
317
|
+
- Document the rollback steps in `IapMigrationNotes.md`.
|
|
318
|
+
|
|
319
|
+
## Step 10 — Test Checklist
|
|
320
|
+
|
|
321
|
+
Include this in `IapMigrationNotes.md` after migration:
|
|
322
|
+
|
|
323
|
+
- [ ] Fresh install — products load and display prices
|
|
324
|
+
- [ ] Upgrade from old app version to migrated version — no duplicate entitlements
|
|
325
|
+
- [ ] Consumable purchase — content granted
|
|
326
|
+
- [ ] Repeat consumable purchase — repeatable, no block
|
|
327
|
+
- [ ] Non-consumable purchase — content granted once
|
|
328
|
+
- [ ] Non-consumable restore — content restored on reinstall
|
|
329
|
+
- [ ] Subscription purchase — subscription active
|
|
330
|
+
- [ ] Subscription restore — status refreshed on launch
|
|
331
|
+
- [ ] Pending purchase (if applicable) — deferred UI shown, no premature grant
|
|
332
|
+
- [ ] Interrupted purchase flow — re-delivered on next launch via `OnPurchasePending`
|
|
333
|
+
- [ ] Backend validation success — entitlement granted
|
|
334
|
+
- [ ] Backend validation failure — entitlement NOT granted, purchase not confirmed
|
|
335
|
+
- [ ] Network failure during validation — purchase left pending, re-delivered on next launch
|
|
336
|
+
- [ ] App killed during purchase — pending order re-delivered on next launch
|
|
337
|
+
- [ ] App resumed after Google purchase UI — `OnPurchasePending` fires correctly
|
|
338
|
+
- [ ] Sandbox tester account — no real charges
|
|
339
|
+
- [ ] Internal testing track build
|
|
340
|
+
- [ ] Play Console product ID match — all IDs match exactly
|
|
341
|
+
- [ ] Play Console base plan compatibility — no advanced offer config that Unity IAP cannot reach
|
|
342
|
+
- [ ] No duplicate entitlement grant
|
|
343
|
+
- [ ] No unacknowledged purchases remaining
|
|
344
|
+
- [ ] No double consumption of consumables
|
|
345
|
+
|
|
346
|
+
## Step 11 — Questions to Ask (only when required)
|
|
347
|
+
|
|
348
|
+
Ask only when the information cannot be inferred:
|
|
349
|
+
|
|
350
|
+
1. Which product IDs are consumable, non-consumable, or subscription?
|
|
351
|
+
2. Does the backend currently validate Google purchase tokens directly (raw `purchaseToken` field)?
|
|
352
|
+
3. Are any subscriptions using multiple base plans or offer tokens?
|
|
353
|
+
4. Should the skill preserve the old public C# billing API as a compatibility facade?
|
|
354
|
+
5. Should native billing files be kept, disabled, or removed?
|
|
355
|
+
|
|
356
|
+
If enough information can be inferred, proceed with a best-effort plan and mark uncertain items as **TODO**.
|