@aqian0/dsh-unity 0.0.0-stage → 0.1.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/CHANGELOG.md +53 -0
- package/LICENSE-UNITY-COMPANION.md +122 -0
- package/LICENSE.md +31 -0
- package/NOTICE.md +90 -0
- package/README.md +273 -2
- package/cordis.patch.yml +22 -0
- package/docs/design.md +297 -0
- package/icon.svg +16 -0
- package/lib/frontmatter.js +392 -0
- package/lib/gating.js +105 -0
- package/lib/harness.js +16 -0
- package/lib/index.js +171 -0
- package/lib/project.js +210 -0
- package/lib/registry.js +268 -0
- package/lib/requirements.js +214 -0
- package/lib/skills.js +191 -0
- package/lib/types/frontmatter.d.ts +84 -0
- package/lib/types/gating.d.ts +80 -0
- package/lib/types/harness.d.ts +152 -0
- package/lib/types/index.d.ts +75 -0
- package/lib/types/project.d.ts +93 -0
- package/lib/types/registry.d.ts +96 -0
- package/lib/types/requirements.d.ts +67 -0
- package/lib/types/skills.d.ts +54 -0
- package/lib/types/watch.d.ts +34 -0
- package/lib/watch.js +84 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +70 -4
- package/skills/2d-pixel-perfect/SKILL.md +208 -0
- package/skills/2d-pixel-perfect/references/api-reference.md +81 -0
- package/skills/2d-pixel-perfect/references/camera-setup-builtin.cs +40 -0
- package/skills/2d-pixel-perfect/references/camera-setup-urp.cs +49 -0
- package/skills/2d-pixel-perfect/references/pipeline-detection.cs +50 -0
- package/skills/2d-pixel-perfect/references/sprite-settings.cs +37 -0
- package/skills/asset-transformer-toolkit/SECURITY.md +15 -0
- package/skills/asset-transformer-toolkit/SKILL.md +39 -0
- package/skills/asset-transformer-toolkit/references/create-importer.md +121 -0
- package/skills/asset-transformer-toolkit/references/lods.md +61 -0
- package/skills/asset-transformer-toolkit/references/rule-api.md +154 -0
- package/skills/asset-transformer-toolkit/references/ruleblock-api.md +37 -0
- package/skills/asset-transformer-toolkit/references/ruleset-api.md +138 -0
- package/skills/asset-transformer-toolkit/references/rulesets-and-actions.md +227 -0
- package/skills/audio-setup-mixers/SECURITY.md +16 -0
- package/skills/audio-setup-mixers/SKILL.md +127 -0
- package/skills/audio-setup-mixers/references/api.md +162 -0
- package/skills/build-gtk/SECURITY.md +16 -0
- package/skills/build-gtk/SKILL.md +200 -0
- package/skills/build-gtk/references/api-reference.md +33 -0
- package/skills/build-gtk/references/graph-api-gaps.md +96 -0
- package/skills/build-gtk/references/runtime-and-visualization.md +191 -0
- package/skills/build-gtk/references/state-machine-api.md +270 -0
- package/skills/build-gtk/references/where-the-docs-stop.md +49 -0
- package/skills/build-live-game/SKILL.md +159 -0
- package/skills/build-live-game/references/achievements.md +757 -0
- package/skills/build-live-game/references/apis.md +271 -0
- package/skills/build-live-game/references/authentication.md +431 -0
- package/skills/build-live-game/references/battlepass.md +904 -0
- package/skills/build-live-game/references/blueprints-and-samples.md +75 -0
- package/skills/build-live-game/references/cloud-code-cloudbehaviours.md +1111 -0
- package/skills/build-live-game/references/cloud-code-modules.md +1276 -0
- package/skills/build-live-game/references/cloud-code.md +58 -0
- package/skills/build-live-game/references/cloud-save.md +464 -0
- package/skills/build-live-game/references/deployment.md +231 -0
- package/skills/build-live-game/references/orientation.md +30 -0
- package/skills/build-live-game/references/player-account.md +821 -0
- package/skills/build-live-game/references/remote-config.md +96 -0
- package/skills/build-live-game/references/services-overview.md +76 -0
- package/skills/build-live-game/references/tooling.md +375 -0
- package/skills/build-live-game/references/ugs-cli.md +86 -0
- package/skills/craft-game-floors/SECURITY.md +23 -0
- package/skills/craft-game-floors/SKILL.md +134 -0
- package/skills/craft-game-floors/references/art-direction.md +85 -0
- package/skills/craft-game-floors/references/camera-rigs.md +51 -0
- package/skills/craft-game-floors/references/character-motion.md +35 -0
- package/skills/craft-game-floors/references/game-audio.md +47 -0
- package/skills/craft-game-floors/references/game-feel.md +68 -0
- package/skills/craft-game-floors/references/game-shell.md +45 -0
- package/skills/craft-game-floors/references/live-floor.md +35 -0
- package/skills/craft-game-floors/references/placeholder-assets.md +35 -0
- package/skills/craft-game-floors/references/scene-lighting.md +52 -0
- package/skills/craft-game-floors/references/toon-shading.md +34 -0
- package/skills/craft-game-floors/references/vfx.md +40 -0
- package/skills/craft-game-floors/references/visual-scorecard.md +43 -0
- package/skills/create-2d-physics/SECURITY.md +16 -0
- package/skills/create-2d-physics/SKILL.md +128 -0
- package/skills/create-2d-physics/references/2d-physics-core.md +155 -0
- package/skills/create-2d-physics/references/legacy-2d-physics.md +45 -0
- package/skills/create-tile-palette-or-rule-tiles/SKILL.md +95 -0
- package/skills/create-tile-palette-or-rule-tiles/references/hexagonalruletile.md +71 -0
- package/skills/create-tile-palette-or-rule-tiles/references/palette-create.md +38 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile-createempty.md +37 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile-createfromsegment.md +219 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile.md +95 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/CreatePaletteTemplate.cs +148 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/ManualWorkflowExample.cs +63 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/RuleTileGenerator.cs +61 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/TilemapRuleTileCreateFromSegment.cs +225 -0
- package/skills/fix-3d-physics-collisions/SECURITY.md +17 -0
- package/skills/fix-3d-physics-collisions/SKILL.md +139 -0
- package/skills/fix-3d-physics-collisions/references/collision-checklist.md +80 -0
- package/skills/fix-3d-physics-collisions/references/collision-debugger.md +18 -0
- package/skills/fix-3d-physics-collisions/references/console-errors-table.md +9 -0
- package/skills/fix-3d-physics-collisions/references/kinematic-trigger-facts.md +18 -0
- package/skills/fix-3d-physics-collisions/references/other-symptoms.md +29 -0
- package/skills/fix-3d-physics-collisions/references/raycast-checklist.md +8 -0
- package/skills/fix-3d-physics-collisions/references/topic-map.md +42 -0
- package/skills/fix-3d-physics-collisions/references/trigger-checklist.md +9 -0
- package/skills/fix-3d-physics-collisions/scripts/CollisionDebugger.cs +561 -0
- package/skills/generate-editor-search-query/SECURITY.md +17 -0
- package/skills/generate-editor-search-query/SKILL.md +117 -0
- package/skills/generate-editor-search-query/references/open-search-window.md +70 -0
- package/skills/generate-editor-search-query/references/query-patterns.md +124 -0
- package/skills/implement-in-app-purchases/SKILL.md +82 -0
- package/skills/implement-in-app-purchases/references/api-details.md +41 -0
- package/skills/implement-in-app-purchases/references/api-notes.md +105 -0
- package/skills/implement-in-app-purchases/references/codeless-catalog.md +197 -0
- package/skills/implement-in-app-purchases/references/convert-adapty.md +270 -0
- package/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
- package/skills/implement-in-app-purchases/references/convert-revenuecat.md +277 -0
- package/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
- package/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +46 -0
- package/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +197 -0
- package/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +302 -0
- package/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +357 -0
- package/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +253 -0
- package/skills/implement-in-app-purchases/references/platform-notes.md +55 -0
- package/skills/implement-in-app-purchases/references/pre-check.md +207 -0
- package/skills/implement-in-app-purchases/references/topic-map.md +46 -0
- package/skills/initialize-ai-navigation/SKILL.md +109 -0
- package/skills/initialize-ai-navigation/references/navigation-system.md +793 -0
- package/skills/initialize-ai-navigation/references/topic-map.md +66 -0
- package/skills/levelplay-unity-integration/SKILL.md +122 -0
- package/skills/levelplay-unity-integration/references/adding-more-ad-formats.md +15 -0
- package/skills/levelplay-unity-integration/references/banner-api.md +927 -0
- package/skills/levelplay-unity-integration/references/best-practices.md +604 -0
- package/skills/levelplay-unity-integration/references/dependency-resolution.md +94 -0
- package/skills/levelplay-unity-integration/references/examples.md +10 -0
- package/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
- package/skills/levelplay-unity-integration/references/initialization-api.md +851 -0
- package/skills/levelplay-unity-integration/references/interstitial-api.md +907 -0
- package/skills/levelplay-unity-integration/references/ios-setup.md +463 -0
- package/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
- package/skills/levelplay-unity-integration/references/privacy-settings.md +593 -0
- package/skills/levelplay-unity-integration/references/production-release-checklist.md +22 -0
- package/skills/levelplay-unity-integration/references/rewarded-api.md +918 -0
- package/skills/levelplay-unity-integration/references/step-0-new-or-migration.md +8 -0
- package/skills/levelplay-unity-integration/references/step-1-verify-environment.md +4 -0
- package/skills/levelplay-unity-integration/references/step-10-testing.md +15 -0
- package/skills/levelplay-unity-integration/references/step-2-business-goals.md +12 -0
- package/skills/levelplay-unity-integration/references/step-3-install-sdk.md +55 -0
- package/skills/levelplay-unity-integration/references/step-4-native-dependencies.md +22 -0
- package/skills/levelplay-unity-integration/references/step-5-app-key-and-ad-units.md +18 -0
- package/skills/levelplay-unity-integration/references/step-6-5-privacy-and-regulation.md +51 -0
- package/skills/levelplay-unity-integration/references/step-6-admob-keys.md +16 -0
- package/skills/levelplay-unity-integration/references/step-7-initialize.md +50 -0
- package/skills/levelplay-unity-integration/references/step-8-ad-unit-strategy.md +16 -0
- package/skills/levelplay-unity-integration/references/step-9-implement-ad-units.md +66 -0
- package/skills/levelplay-unity-integration/references/testing-and-validation.md +222 -0
- package/skills/levelplay-unity-integration/references/troubleshooting.md +99 -0
- package/skills/localize-unity-project/SKILL.md +159 -0
- package/skills/localize-unity-project/references/api-notes.md +15 -0
- package/skills/localize-unity-project/references/cjk-fonts.md +83 -0
- package/skills/localize-unity-project/references/docs-map.md +42 -0
- package/skills/localize-unity-project/references/documentation-lookup.md +33 -0
- package/skills/localize-unity-project/references/locale-switching.md +17 -0
- package/skills/localize-unity-project/references/table-completeness-check.md +47 -0
- package/skills/localize-unity-project/references/translating-existing-project.md +47 -0
- package/skills/localize-unity-project/references/translation-strategy.md +41 -0
- package/skills/localize-unity-project/references/troubleshooting.md +12 -0
- package/skills/localize-unity-project/scripts/L10nBatchProcessor.cs +191 -0
- package/skills/localize-unity-project/scripts/LocalizedFontAsset.cs +18 -0
- package/skills/manage-sprite-atlas/SKILL.md +202 -0
- package/skills/manage-sprite-atlas/references/addressables-delivery.md +58 -0
- package/skills/manage-sprite-atlas/references/advanced-manual-authoring.md +19 -0
- package/skills/manage-sprite-atlas/references/api.md +382 -0
- package/skills/manage-sprite-atlas/references/best-practices.md +183 -0
- package/skills/manage-sprite-atlas/references/common-errors.md +123 -0
- package/skills/manage-sprite-atlas/references/complete-workflow.md +61 -0
- package/skills/manage-sprite-atlas/references/custom-packing.md +147 -0
- package/skills/manage-sprite-atlas/references/delivery-mechanism.md +30 -0
- package/skills/manage-sprite-atlas/references/key-requirements.md +21 -0
- package/skills/manage-sprite-atlas/references/manual-authoring.md +39 -0
- package/skills/manage-sprite-atlas/references/namespaces.md +15 -0
- package/skills/manage-sprite-atlas/references/v2-architecture.md +21 -0
- package/skills/manage-sprite-atlas/resources/authoringvsruntime.cs +176 -0
- package/skills/manage-sprite-atlas/resources/buildaddressablespostprocess.cs +59 -0
- package/skills/manage-sprite-atlas/resources/cacheloadedatlases.cs +145 -0
- package/skills/manage-sprite-atlas/resources/cleanupbatchoperations.cs +119 -0
- package/skills/manage-sprite-atlas/resources/createandconfiguremasteratlas.cs +57 -0
- package/skills/manage-sprite-atlas/resources/custompackersetup.cs +88 -0
- package/skills/manage-sprite-atlas/resources/deprecatedmethods.cs +142 -0
- package/skills/manage-sprite-atlas/resources/dontmodifywithoutsaving.cs +120 -0
- package/skills/manage-sprite-atlas/resources/dontpackinruntimebuilds.cs +190 -0
- package/skills/manage-sprite-atlas/resources/dontscriptspriteatlasineditor.cs +114 -0
- package/skills/manage-sprite-atlas/resources/editorconfiguration.cs +95 -0
- package/skills/manage-sprite-atlas/resources/enablespritepacking.cs +172 -0
- package/skills/manage-sprite-atlas/resources/gridspritepacker.cs +50 -0
- package/skills/manage-sprite-atlas/resources/handlelatebinding.cs +147 -0
- package/skills/manage-sprite-atlas/resources/handlenullcases.cs +141 -0
- package/skills/manage-sprite-atlas/resources/migratev1tov2.cs +335 -0
- package/skills/manage-sprite-atlas/resources/multipagepacker.cs +80 -0
- package/skills/manage-sprite-atlas/resources/optimizetexturesettings.cs +191 -0
- package/skills/manage-sprite-atlas/resources/packerdebugging.cs +158 -0
- package/skills/manage-sprite-atlas/resources/packtransform.cs +51 -0
- package/skills/manage-sprite-atlas/resources/platformnames.cs +127 -0
- package/skills/manage-sprite-atlas/resources/queryspritesefficiently.cs +222 -0
- package/skills/manage-sprite-atlas/resources/registercallbacks.cs +152 -0
- package/skills/manage-sprite-atlas/resources/runtimeatlasloader.cs +15 -0
- package/skills/manage-sprite-atlas/resources/runtimespriteaccess.cs +19 -0
- package/skills/manage-sprite-atlas/resources/savespriteatlasasset.cs +107 -0
- package/skills/manage-sprite-atlas/resources/scriptablepacker.cs +81 -0
- package/skills/manage-sprite-atlas/resources/setincludeinbuild.cs +164 -0
- package/skills/manage-sprite-atlas/resources/sizeoptimizedpacker.cs +88 -0
- package/skills/manage-sprite-atlas/resources/spriteatlaslatebinding.cs +123 -0
- package/skills/manage-sprite-atlas/resources/spriteatlasprebuildgenerator.cs +219 -0
- package/skills/manage-sprite-atlas/resources/spritedata.cs +35 -0
- package/skills/manage-sprite-atlas/resources/spritepack.cs +39 -0
- package/skills/manage-sprite-atlas/resources/texturedata.cs +15 -0
- package/skills/manage-sprite-atlas/resources/updatebuildscripts.cs +357 -0
- package/skills/manage-sprite-atlas/resources/updatesettingsconfiguration.cs +135 -0
- package/skills/manage-sprite-atlas/resources/usevariantswisely.cs +179 -0
- package/skills/manage-sprite-atlas/resources/variantatlas.cs +39 -0
- package/skills/migrate-birp-to-urp/SECURITY.md +16 -0
- package/skills/migrate-birp-to-urp/SKILL.md +167 -0
- package/skills/migrate-birp-to-urp/references/capturing-the-editor.md +66 -0
- package/skills/migrate-birp-to-urp/references/complex-shader-situations.md +272 -0
- package/skills/migrate-birp-to-urp/references/conversion-and-rendering-triage.md +113 -0
- package/skills/migrate-birp-to-urp/references/custom-shader-triage.md +123 -0
- package/skills/migrate-birp-to-urp/references/implementation-patterns.md +529 -0
- package/skills/migrate-birp-to-urp/references/migration-workflow.md +265 -0
- package/skills/migrate-birp-to-urp/references/parity-validation-and-troubleshooting.md +114 -0
- package/skills/migrate-birp-to-urp/references/preflight-and-urp-setup.md +195 -0
- package/skills/migrate-birp-to-urp/references/quality-settings-map.md +69 -0
- package/skills/new-unity-project/SECURITY.md +26 -0
- package/skills/new-unity-project/SKILL.md +171 -0
- package/skills/new-unity-project/references/checklist.md +18 -0
- package/skills/new-unity-project/references/common-mistakes.md +15 -0
- package/skills/new-unity-project/references/skill-setup.md +66 -0
- package/skills/new-unity-project/references/step-1-concept.md +13 -0
- package/skills/new-unity-project/references/step-2-platforms-and-create.md +31 -0
- package/skills/new-unity-project/references/step-3-join-and-reconcile.md +16 -0
- package/skills/new-unity-project/references/step-4-source-control.md +9 -0
- package/skills/new-unity-project/references/step-5-packages.md +18 -0
- package/skills/new-unity-project/references/step-6-identity-and-floors.md +20 -0
- package/skills/new-unity-project/references/step-7-visual-baseline.md +75 -0
- package/skills/new-unity-project/references/step-8-first-commit.md +21 -0
- package/skills/new-unity-project/references/step-9-handoff.md +23 -0
- package/skills/optimize-audio/SECURITY.md +16 -0
- package/skills/optimize-audio/SKILL.md +120 -0
- package/skills/optimize-audio/references/diagnostics.md +42 -0
- package/skills/optimize-audio/references/troubleshooting.md +41 -0
- package/skills/optimize-audio/resources/audio-import-api.md +149 -0
- package/skills/optimize-audio/resources/platform-settings.md +48 -0
- package/skills/optimize-text-mesh-pro/SKILL.md +181 -0
- package/skills/optimize-text-mesh-pro/references/dynamic-atlas-and-profiling.md +28 -0
- package/skills/optimize-text-mesh-pro/references/topic-map.md +36 -0
- package/skills/optimize-web/SECURITY.md +16 -0
- package/skills/optimize-web/SKILL.md +157 -0
- package/skills/optimize-web/references/editor-csharp.md +120 -0
- package/skills/optimize-web/references/topic-map.md +49 -0
- package/skills/optimize-web/references/troubleshooting.md +45 -0
- package/skills/optimize-web/references/understand-request.md +19 -0
- package/skills/optimize-web/references/web-assets-quality.md +59 -0
- package/skills/optimize-web/references/web-player-settings.md +39 -0
- package/skills/optimize-web/references/web-profiling-memory.md +71 -0
- package/skills/optimize-web/scripts/WebOptimizer.cs +46 -0
- package/skills/optimize-web/scripts/toktx-examples.sh +11 -0
- package/skills/setup-multiplayer-services/SKILL.md +36 -0
- package/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
- package/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
- package/skills/setup-multiplayer-services/references/examples.md +33 -0
- package/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
- package/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
- package/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
- package/skills/setup-vivox-voice-chat/SECURITY.md +16 -0
- package/skills/setup-vivox-voice-chat/SKILL.md +166 -0
- package/skills/setup-vivox-voice-chat/references/api-reference-lookup.md +28 -0
- package/skills/setup-vivox-voice-chat/references/docs-topic-map.md +13 -0
- package/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
- package/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
- package/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
- package/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
- package/skills/setup-vivox-voice-chat/references/voice-channels.md +92 -0
- package/skills/shader-graph-create-custom-node/SKILL.md +25 -0
- package/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
- package/skills/sprite-editor/SECURITY.md +16 -0
- package/skills/sprite-editor/SKILL.md +66 -0
- package/skills/sprite-editor/references/api_reference.md +151 -0
- package/skills/sprite-editor/references/background.md +112 -0
- package/skills/sprite-editor/references/templates.md +72 -0
- package/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
- package/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
- package/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
- package/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
- package/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
- package/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
- package/skills/sprite-editor/scripts/README.md +134 -0
- package/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
- package/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
- package/skills/sprite-segment-3x3grid/SKILL.md +177 -0
- package/skills/sprite-segment-3x3grid/references/topic-map.md +37 -0
- package/skills/sprite-segment-3x3grid/scripts/SpriteGridAnalysis.cs +119 -0
- package/skills/ui/SKILL.md +142 -0
- package/skills/ui-imgui/SKILL.md +180 -0
- package/skills/ui-imgui/references/gui-elements.md +156 -0
- package/skills/ui-imgui/references/templates.md +141 -0
- package/skills/ui-ugui/SKILL.md +217 -0
- package/skills/ui-ugui/references/layout-and-anchors.md +61 -0
- package/skills/ui-ugui/references/scrollview-setup.md +29 -0
- package/skills/ui-uitk/SKILL.md +229 -0
- package/skills/ui-uitk/references/common-issues.md +74 -0
- package/skills/ui-uitk/references/custom-elements.md +241 -0
- package/skills/ui-uitk/references/painter2d.md +282 -0
- package/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
- package/skills/ui-uitk/references/svg-icons.md +136 -0
- package/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
- package/skills/ui-uitk/references/uss-guide.md +138 -0
- package/skills/unity-cli/CHANGELOG.md +524 -0
- package/skills/unity-cli/SECURITY.md +68 -0
- package/skills/unity-cli/SKILL.md +160 -0
- package/skills/unity-cli/references/auth-license-cloud.md +318 -0
- package/skills/unity-cli/references/bootstrap-project.md +177 -0
- package/skills/unity-cli/references/build-run-test.md +555 -0
- package/skills/unity-cli/references/catalog-plugins.md +86 -0
- package/skills/unity-cli/references/ci-recipes.md +76 -0
- package/skills/unity-cli/references/cloud-automation.md +819 -0
- package/skills/unity-cli/references/cloud-workflows.md +19 -0
- package/skills/unity-cli/references/collaboration.md +533 -0
- package/skills/unity-cli/references/config-hub.md +239 -0
- package/skills/unity-cli/references/diagnostics-maintenance.md +718 -0
- package/skills/unity-cli/references/docs-workflow.md +179 -0
- package/skills/unity-cli/references/editor-targeting.md +29 -0
- package/skills/unity-cli/references/editors-install.md +490 -0
- package/skills/unity-cli/references/environment-variables.md +42 -0
- package/skills/unity-cli/references/exit-codes.md +47 -0
- package/skills/unity-cli/references/global-flags.md +32 -0
- package/skills/unity-cli/references/integration-advanced.md +1130 -0
- package/skills/unity-cli/references/notes.md +20 -0
- package/skills/unity-cli/references/notifications.md +39 -0
- package/skills/unity-cli/references/playmode-verification-loop.md +279 -0
- package/skills/unity-cli/references/projects-templates.md +997 -0
- package/skills/unity-cli/references/scene-editing-preflight.md +25 -0
- package/skills/unity-cli/references/setup-and-help.md +54 -0
- package/skills/unity-cli/references/version-control.md +612 -0
- package/skills/unity-package-management/SKILL.md +169 -0
- package/skills/unity-package-management/references/discovering-packages.md +66 -0
- package/skills/unity-package-management/references/headless-run.md +31 -0
- package/skills/unity-package-management/references/installer-script.md +92 -0
- package/skills/unity-package-management/references/select-packages.md +126 -0
- package/skills/unity-pipeline/SECURITY.md +17 -0
- package/skills/unity-pipeline/SKILL.md +205 -0
- package/skills/unity-pipeline/references/csharp-eval.md +23 -0
- package/skills/unity-pipeline/references/multiplayer-play-mode.md +103 -0
- package/skills/urp-postprocessing/SECURITY.md +16 -0
- package/skills/urp-postprocessing/SKILL.md +188 -0
- package/skills/urp-postprocessing/references/code-templates.md +150 -0
- package/skills/urp-postprocessing/references/effect-reference.md +86 -0
- package/skills/validate-urp-render-graph-renderer-feature/SKILL.md +92 -0
- package/skills/validate-urp-render-graph-renderer-feature/references/validation-checklist.md +179 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# Convert Native iOS StoreKit to Unity IAP 5
|
|
2
|
+
|
|
3
|
+
Links to other reference files point to files in this `references/` folder. Any other relative paths resolve to the skill directory.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Trigger Phrases](#trigger-phrases)
|
|
8
|
+
- [Important Constraints](#important-constraints)
|
|
9
|
+
- [Step 1 — Pre-Conversion Scan](#step-1--pre-conversion-scan)
|
|
10
|
+
- [Step 2 — StoreKit Version Detection](#step-2--storekit-version-detection)
|
|
11
|
+
- [Step 3 — Product Classification](#step-3--product-classification)
|
|
12
|
+
- [Step 4 — Migration Report (produce before any edits)](#step-4--migration-report-produce-before-any-edits)
|
|
13
|
+
- [Step 5 — Blocker Detection](#step-5--blocker-detection)
|
|
14
|
+
- [Step 6 — Target Architecture](#step-6--target-architecture)
|
|
15
|
+
- [Step 7 — Migration Phases](#step-7--migration-phases)
|
|
16
|
+
- [Step 8 — Behavior Change Rules](#step-8--behavior-change-rules)
|
|
17
|
+
- [Step 9 — Native → Unity IAP Concept Mapping](#step-9--native--unity-iap-concept-mapping)
|
|
18
|
+
- [Step 10 — Rollback Plan](#step-10--rollback-plan)
|
|
19
|
+
- [Step 11 — Test Checklist](#step-11--test-checklist)
|
|
20
|
+
- [Step 12 — Questions to Ask (only when required)](#step-12--questions-to-ask-only-when-required)
|
|
21
|
+
|
|
22
|
+
Use this reference when the project uses a custom native iOS StoreKit plugin (Objective-C or Swift, bridged into Unity via `[DllImport("__Internal")]` and `UnitySendMessage`) and needs to be migrated to `com.unity.purchasing`. Always install the latest stable version.
|
|
23
|
+
|
|
24
|
+
## Trigger Phrases
|
|
25
|
+
|
|
26
|
+
- "Convert native StoreKit to Unity IAP"
|
|
27
|
+
- "Migrate SKPaymentQueue integration to Unity IAP"
|
|
28
|
+
- "Replace custom iOS billing plugin with Unity IAP"
|
|
29
|
+
- "Remove native StoreKit and use Unity IAP"
|
|
30
|
+
- "Migrate DllImport StoreKit bridge to Unity IAP"
|
|
31
|
+
- "Replace SKProduct / SKPayment with Unity IAP"
|
|
32
|
+
|
|
33
|
+
## Important Constraints
|
|
34
|
+
|
|
35
|
+
- **Do not delete existing native iOS plugin files unless explicitly requested.** Always preserve with `#if !USE_UNITY_IAP_V5` guards on the C# side. ObjC/Swift files cannot use C# defines — guard their call sites in C# instead.
|
|
36
|
+
- **Create the new Unity IAP adapter first**, then mark the old native adapter as deprecated.
|
|
37
|
+
- **Preserve public game-facing APIs** via a compatibility facade so gameplay code does not need large rewrites.
|
|
38
|
+
- **Do not change product IDs.**
|
|
39
|
+
- **Do not change backend validation endpoints** unless the receipt format change makes it unavoidable — document any backend change required. The receipt format change from SK1 bundle to per-transaction JWS is a breaking backend change; flag it prominently.
|
|
40
|
+
- **Do not grant purchases on the client** if the existing project uses server-side validation.
|
|
41
|
+
- **Do not assume all products are consumables.** Detect and classify each product.
|
|
42
|
+
- **Do not assume subscriptions are simple.** Detect promotional offers, offer codes, and introductory price usage. If found, surface as migration blockers and let the user choose a path.
|
|
43
|
+
- **If the project contains RevenueCat, Adapty, or Essential Kit**, stop and notify the user — this skill does not support converting those packages.
|
|
44
|
+
- **If StoreKit-specific features are not cleanly expressible in Unity IAP**, report them as migration blockers rather than silently removing them.
|
|
45
|
+
- **A mixed Unity IAP + native StoreKit architecture is not recommended.** Both systems register as `SKPaymentQueue` observers — only one reliably receives transaction callbacks. Do not offer a mixed approach; if the user asks, explain the risk and redirect to Option A or B (see Subscription Blocker Options).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 1 — Pre-Conversion Scan
|
|
50
|
+
|
|
51
|
+
Scan before making any changes. Do not edit files until the migration report is accepted.
|
|
52
|
+
|
|
53
|
+
### 1a — Native iOS Plugin Files
|
|
54
|
+
|
|
55
|
+
Search `Assets/Plugins/iOS/` for:
|
|
56
|
+
- `*.m`, `*.mm` files — Objective-C plugins
|
|
57
|
+
- `*.h` files — headers with StoreKit imports or `extern "C"` bridge declarations
|
|
58
|
+
- `*.swift` files — Swift plugins (rare but increasingly common)
|
|
59
|
+
|
|
60
|
+
List all files found. For each, note whether it imports `StoreKit` or `StoreKit2`.
|
|
61
|
+
|
|
62
|
+
### 1b — C# Bridge Patterns
|
|
63
|
+
|
|
64
|
+
Search `Assets/**/*.cs` for:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
DllImport.*__Internal
|
|
68
|
+
UnitySendMessage
|
|
69
|
+
SKProduct|SKPayment|SKPaymentTransaction|SKPaymentQueue|SKReceiptRefresh
|
|
70
|
+
StoreKit|AppStore|AppleIAP|iOSBilling|iOSIAP|iOSPurchase
|
|
71
|
+
Application\.platform.*IPhonePlayer|RuntimePlatform\.IPhonePlayer
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Also search for callback method names referenced in `UnitySendMessage` calls in the native files — these will be C# methods receiving callbacks.
|
|
75
|
+
|
|
76
|
+
### 1c — StoreKit 1 Patterns (in .m / .mm / .h files)
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
SKProductsRequest|SKProductsRequestDelegate
|
|
80
|
+
SKPaymentQueue|SKPaymentTransactionObserver
|
|
81
|
+
SKPaymentTransaction|SKPayment|SKMutablePayment
|
|
82
|
+
SKProduct|SKProductSubscriptionPeriod|SKProductDiscount
|
|
83
|
+
paymentQueue:updatedTransactions:|finishTransaction:
|
|
84
|
+
SKReceiptRefreshRequest
|
|
85
|
+
SKPaymentDiscount|paymentDiscount
|
|
86
|
+
SKStorefront|paymentQueueDidChangeStorefront
|
|
87
|
+
canMakePayments
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 1d — StoreKit 2 Patterns (in .swift files)
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
import StoreKit
|
|
94
|
+
Product\.products\(for:\)|product\.purchase\(\)
|
|
95
|
+
Transaction\.currentEntitlements|Transaction\.updates|Transaction\.finish
|
|
96
|
+
verificationResult|JWSTransaction
|
|
97
|
+
winBackOffer|eligibleWinBackOffers
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 1e — Scene / Prefab / Asset Scan
|
|
101
|
+
|
|
102
|
+
Search `.unity`, `.prefab`, `.asset` files for references to billing-related MonoBehaviour names found in 1b. List all scene references so they can be rewired after migration.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Step 2 — StoreKit Version Detection
|
|
107
|
+
|
|
108
|
+
Classify the native plugin as **StoreKit 1**, **StoreKit 2**, or **Mixed** based on Step 1 findings.
|
|
109
|
+
|
|
110
|
+
| Generation | Signals | Notes |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| **StoreKit 1** | `SKPaymentQueue`, `SKPaymentTransaction`, `SKProductsRequest` | Most Unity projects pre-2023 |
|
|
113
|
+
| **StoreKit 2** | `Product.products(for:)`, `Transaction.currentEntitlements`, `Transaction.updates` | Swift 5.5+, iOS 15+ |
|
|
114
|
+
| **Mixed** | Both sets of signals present | Treat as StoreKit 1 for blocker purposes; flag SK2 usage for review |
|
|
115
|
+
|
|
116
|
+
Document the detected generation in the migration report. StoreKit 2 has additional blockers (see Step 5).
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Step 3 — Product Classification
|
|
121
|
+
|
|
122
|
+
Classify every detected product into one of: **Consumable**, **NonConsumable**, **Subscription**, **Unknown**.
|
|
123
|
+
|
|
124
|
+
Infer from (in priority order):
|
|
125
|
+
|
|
126
|
+
1. `SKProduct.subscriptionPeriod` non-nil → **Subscription**
|
|
127
|
+
2. `finishTransaction:` called after grant without a "restore" path → **Consumable**
|
|
128
|
+
3. `restoreCompletedTransactions` handling or checking `originalTransaction` → **NonConsumable** or **Subscription**
|
|
129
|
+
4. Product ID naming conventions (`coins`, `gems`, `pack` → Consumable; `remove_ads`, `unlock`, `premium` → NonConsumable; `monthly`, `annual`, `sub` → Subscription)
|
|
130
|
+
5. Entitlement / backend grant code patterns
|
|
131
|
+
6. Comments or config files
|
|
132
|
+
|
|
133
|
+
If type cannot be confidently inferred, mark as **Unknown** and add to the blocker question list.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Step 4 — Migration Report (produce before any edits)
|
|
138
|
+
|
|
139
|
+
Generate all sections before touching any file. Do not skip any.
|
|
140
|
+
|
|
141
|
+
1. **Current native billing architecture** — describe the bridge pattern (C# `[DllImport("__Internal")]` → ObjC/Swift plugin → StoreKit)
|
|
142
|
+
2. **StoreKit generation** — SK1, SK2, or Mixed
|
|
143
|
+
3. **Files using native StoreKit** — full list with role of each file (plugin, bridge, callback receiver, UI)
|
|
144
|
+
4. **Product catalog discovered** — all product IDs found
|
|
145
|
+
5. **Product type mapping** — inferred type + confidence + source of inference for each product
|
|
146
|
+
6. **Purchase flow mapping** — native → Unity IAP step-by-step
|
|
147
|
+
7. **Restore purchase flow mapping** — `restoreCompletedTransactions` / `Transaction.currentEntitlements` → `store.FetchPurchases()` + `store.RestoreTransactions(callback)`
|
|
148
|
+
8. **Backend validation mapping** — what data the old flow sent vs what Unity IAP provides (see Behavior Change Rules — receipt format is a breaking change)
|
|
149
|
+
9. **Transaction finish behavior mapping** — `finishTransaction:` → `store.ConfirmPurchase(pendingOrder)` (only after grant)
|
|
150
|
+
10. **Subscription behavior mapping** — detected subscription products, restore path, renewal handling, introductory price usage
|
|
151
|
+
11. **StoreKit-specific features detected** — list each (see Blocker Detection)
|
|
152
|
+
12. **Migration blockers** — features that cannot be cleanly mapped
|
|
153
|
+
13. **Proposed new Unity IAP architecture** — new files and their roles
|
|
154
|
+
14. **Code files to create** — with paths
|
|
155
|
+
15. **Code files to modify** — with nature of each change
|
|
156
|
+
16. **Manual App Store Connect checks** — product ID match, subscription group configuration
|
|
157
|
+
17. **Test plan** — from the checklist in this document
|
|
158
|
+
18. **Rollback plan** — from the rollback plan section in this document
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Step 5 — Blocker Detection
|
|
163
|
+
|
|
164
|
+
Report these as migration blockers if detected. Do not silently remove them.
|
|
165
|
+
|
|
166
|
+
| Feature | Detection Signal | Blocker Level |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| Promotional offer signing (SK1 `SKPaymentDiscount`) | `SKPaymentDiscount`, `paymentDiscount`, `offerIdentifier`, `keyIdentifier`, `nonce`, `signature` | **Hard** — requires server-side signed offers; Unity IAP has no equivalent |
|
|
169
|
+
| SK2 promotional offer signing | `promotionalOffer`, `PromotionalOffer`, `eligiblePromotionOfferSignature` | **Hard** — not exposed in Unity IAP |
|
|
170
|
+
| Win-back offers (SK2) | `winBackOffer`, `eligibleWinBackOffers` | **Hard** — not supported in Unity IAP 5.4 |
|
|
171
|
+
| `SKReceiptRefreshRequest` (manual receipt refresh) | `SKReceiptRefreshRequest` | **Soft** — `store.FetchPurchases()` covers the re-delivery use case; document loss of explicit refresh |
|
|
172
|
+
| `SKStorefront` / storefront change observer | `SKStorefront`, `paymentQueueDidChangeStorefront` | **Soft** — not exposed in Unity IAP; document loss |
|
|
173
|
+
| Multi-quantity purchases | `quantity > 1` in `SKMutablePayment` | **Hard** — Unity IAP does not support quantity > 1 per transaction |
|
|
174
|
+
| Custom `SKPaymentQueue` observers remaining alongside Unity IAP | Other `addTransactionObserver` calls not being removed | **Hard** — both observers compete; only one reliably receives callbacks |
|
|
175
|
+
| `SKOverlay` / `SKStoreProductViewController` | `SKOverlay`, `SKStoreProductViewController` | **Soft** — not IAP-related; these are store UI overlays. Document as out of scope for this migration |
|
|
176
|
+
| Direct App Store receipt bundle validation (`appStoreReceiptURL`) | `appStoreReceiptURL`, `receiptData`, `/verifyReceipt` in backend URLs | **Hard blocker for backend** — Unity IAP uses per-transaction JWS, not the receipt bundle. Backend must migrate from `/verifyReceipt` to JWS validation |
|
|
177
|
+
|
|
178
|
+
### Subscription Blocker Options (present to user when hard subscription blockers found)
|
|
179
|
+
|
|
180
|
+
**Option A — Remove the blocking feature and simplify App Store Connect setup for Unity IAP compatibility**
|
|
181
|
+
Remove promotional offer signing or simplify subscription configuration so Unity IAP can handle all products without native StoreKit. Recommended — single system, no coexistence risk.
|
|
182
|
+
|
|
183
|
+
**Option B — Stay on native StoreKit for all products**
|
|
184
|
+
Do not migrate at this time. Keep the native StoreKit plugin as-is until the App Store Connect configuration can be simplified or Unity IAP exposes the required features. Stop the conversion and document the blocker and this decision in `IapMigrationNotes.md`.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Step 6 — Target Architecture
|
|
189
|
+
|
|
190
|
+
Create under `Assets/Scripts/IAP/`:
|
|
191
|
+
|
|
192
|
+
| File | Purpose |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `IStorePurchaseService.cs` | Game-facing interface (stable public API) |
|
|
195
|
+
| `UnityIapStorePurchaseService.cs` | Unity IAP 5.x implementation |
|
|
196
|
+
| `ProductCatalogDefinition.cs` | ScriptableObject or plain class holding all `ProductDefinitionEntry` |
|
|
197
|
+
| `ProductDefinitionEntry.cs` | Per-product data: ID, type, store-specific IDs |
|
|
198
|
+
| `PurchaseEntitlementMapper.cs` | Maps Unity IAP order data → game grant calls |
|
|
199
|
+
| `PurchaseValidationRequest.cs` | DTO sent to backend |
|
|
200
|
+
| `PurchaseValidationResult.cs` | DTO received from backend |
|
|
201
|
+
| `PurchaseRestoreResult.cs` | Result of restore operation |
|
|
202
|
+
| `LegacyStoreKitAdapterDeprecated.cs` | Compatibility facade (only if game code calls old StoreKit bridge API directly) |
|
|
203
|
+
| `IapMigrationNotes.md` | Human-readable notes on what changed, blockers found, manual steps |
|
|
204
|
+
|
|
205
|
+
### Game-Facing Interface (preserve or adapt from existing API surface)
|
|
206
|
+
|
|
207
|
+
```csharp
|
|
208
|
+
public interface IStorePurchaseService
|
|
209
|
+
{
|
|
210
|
+
Task InitializeAsync();
|
|
211
|
+
Task FetchProductsAsync();
|
|
212
|
+
IReadOnlyList<StoreProductInfo> GetProducts();
|
|
213
|
+
Task PurchaseAsync(string productId);
|
|
214
|
+
Task RestorePurchasesAsync();
|
|
215
|
+
bool IsInitialized { get; }
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Step 7 — Migration Phases
|
|
222
|
+
|
|
223
|
+
### Phase 1 — Package Check
|
|
224
|
+
|
|
225
|
+
- Verify `com.unity.purchasing` exists in `Packages/manifest.json`.
|
|
226
|
+
- If absent or outdated, install the latest stable version via **Window > Package Manager > Unity Registry > In App Purchasing**. Do not auto-edit `manifest.json` unless the user explicitly allows it.
|
|
227
|
+
- Confirm installation before proceeding.
|
|
228
|
+
|
|
229
|
+
### Phase 2 — Product Catalog Extraction
|
|
230
|
+
|
|
231
|
+
- Extract all product IDs and inferred types from the scan.
|
|
232
|
+
- Generate `ProductCatalogDefinition.cs` / `ProductDefinitionEntry.cs`.
|
|
233
|
+
- Each entry: `productId`, `ProductType`, optional `storeSpecificIds`, `notes`.
|
|
234
|
+
|
|
235
|
+
### Phase 3 — New Unity IAP Service
|
|
236
|
+
|
|
237
|
+
Create `UnityIapStorePurchaseService`:
|
|
238
|
+
|
|
239
|
+
1. **Initialization** — `UnityIAPServices.StoreController()`, subscribe all events **before** `Connect()`.
|
|
240
|
+
2. **Product fetching** — build `List<ProductDefinition>` from catalog, call `store.FetchProducts()`, handle `OnProductsFetched` / `OnProductsFetchFailed`.
|
|
241
|
+
3. **Purchase initiation** — `store.PurchaseProduct(product)`.
|
|
242
|
+
4. **Purchase callback** — `OnPurchasePending`: validate receipt → grant entitlement → `ConfirmPurchase(pendingOrder)`. **Never confirm before grant.**
|
|
243
|
+
5. **Deferred purchases (Ask-to-Buy)** — `OnPurchaseDeferred`: show pending UI, do not grant. When approved, `OnPurchasePending` fires.
|
|
244
|
+
6. **Promotional purchase interception** — if the existing plugin intercepts App Store promotional purchases, wire up:
|
|
245
|
+
```csharp
|
|
246
|
+
if (store.AppleStoreExtendedPurchaseService != null)
|
|
247
|
+
store.AppleStoreExtendedPurchaseService.OnPromotionalPurchaseIntercepted += OnPromotionalPurchase;
|
|
248
|
+
```
|
|
249
|
+
Call `store.AppleStoreExtendedPurchaseService?.ContinuePromotionalPurchases()` when ready to proceed.
|
|
250
|
+
7. **Failed purchases** — `OnPurchaseFailed`: map `FailureReason` to user-facing error.
|
|
251
|
+
8. **Restore** — `store.FetchPurchases()` re-delivers unconfirmed purchases via `OnPurchasePending`. Add `store.RestoreTransactions(callback)` for the explicit "Restore Purchases" button (required on iOS).
|
|
252
|
+
9. **Validation handoff** — send `order.Info.Apple?.jwsRepresentation` to backend in place of the SK1 receipt bundle. Document the backend endpoint change required (see Behavior Change Rules).
|
|
253
|
+
|
|
254
|
+
### Phase 4 — Compatibility Facade
|
|
255
|
+
|
|
256
|
+
If game code calls the old native bridge directly (e.g., `NativeStoreKit.Purchase(id)`):
|
|
257
|
+
|
|
258
|
+
- Create `LegacyStoreKitAdapterDeprecated.cs` that implements the same method signatures.
|
|
259
|
+
- Delegate all calls to `UnityIapStorePurchaseService`.
|
|
260
|
+
- Mark all methods `[Obsolete("Use IStorePurchaseService — remove after migration validation")]`.
|
|
261
|
+
|
|
262
|
+
### Phase 5 — Remove Native Plugin from Active Path
|
|
263
|
+
|
|
264
|
+
- Stop calling `[DllImport("__Internal")]` bridge methods for migrated products.
|
|
265
|
+
- Wrap all native bridge calls in C# with `#if !USE_UNITY_IAP_V5` — do not delete them.
|
|
266
|
+
- Do not delete ObjC/Swift plugin files — leave them in `Assets/Plugins/iOS/`. The `#if` guards on the C# call sites are sufficient to prevent the old bridge from being invoked.
|
|
267
|
+
- If the existing plugin registers its own `SKPaymentQueue` observer (common), add a note in `IapMigrationNotes.md` that the plugin's observer registration must be removed or disabled before shipping — both observers competing for the same queue is a hard conflict.
|
|
268
|
+
|
|
269
|
+
### Phase 6 — Test Scaffolding
|
|
270
|
+
|
|
271
|
+
- Add editor stubs for sandbox testing.
|
|
272
|
+
- Add the QA checklist from the test plan below to `IapMigrationNotes.md`.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Step 8 — Behavior Change Rules
|
|
277
|
+
|
|
278
|
+
These are the changes that break games or backends after the switch. For the Unity IAP side of each call, read the docs page named in the Full topic map of the parent skill file, and the Apple notes in [platform-notes.md](platform-notes.md).
|
|
279
|
+
|
|
280
|
+
- **The receipt format changes for the backend.** Unity IAP uses StoreKit 2 on iOS 15+, so each transaction has its own JWS (`order.Info.Apple?.jwsRepresentation`) instead of the SK1 base64 app receipt. If the backend calls `/verifyReceipt`, list a migration to Apple's App Store Server API as a required backend change in `IapMigrationNotes.md`.
|
|
281
|
+
- **One call finishes every transaction.** `ConfirmPurchase(pendingOrder)` replaces `finishTransaction` for all product types. Call it only after the entitlement is granted and saved, because a finished transaction is never re-delivered.
|
|
282
|
+
- **Startup checks and restore are separate.** Call `store.FetchPurchases()` at startup to re-deliver unconfirmed purchases. Use `store.RestoreTransactions(callback)` only for the user's "Restore Purchases" button.
|
|
283
|
+
- **`applicationUsername` becomes `SetAppAccountToken(Guid)`**, called after `await store.Connect()`. It takes a `Guid`, not a string hash, so if the native code used a hash, ask the user how to map their account IDs to a `Guid`.
|
|
284
|
+
- **Ask-to-Buy maps to `OnPurchaseDeferred`.** Show a pending state and don't grant; the approved purchase arrives through `OnPurchasePending`.
|
|
285
|
+
- **Promotional purchases and the code redemption sheet** move to `AppleStoreExtendedPurchaseService`, which exists only after `Connect()` on Apple platforms.
|
|
286
|
+
|
|
287
|
+
## Step 9 — Native → Unity IAP Concept Mapping
|
|
288
|
+
|
|
289
|
+
Only the mappings that aren't one-to-one renames, or that agents commonly get wrong:
|
|
290
|
+
|
|
291
|
+
| Native StoreKit | Unity IAP 5.x |
|
|
292
|
+
|---|---|
|
|
293
|
+
| `SKProduct` / SK2 `Product` | `Product`, from `store.GetProductById` after `OnProductsFetched` |
|
|
294
|
+
| `SKPaymentTransaction` / SK2 `Transaction` | `PendingOrder`, from `OnPurchasePending` |
|
|
295
|
+
| `transactionIdentifier` | `pendingOrder.Info.TransactionID` |
|
|
296
|
+
| `SKPaymentTransactionStateRestored` | `OnPurchasesFetched` (from `FetchPurchases`) or `OnPurchasePending` (from `RestoreTransactions`) |
|
|
297
|
+
| SK2 `Transaction.updates` | `store.OnPurchasePending` |
|
|
298
|
+
| SK2 `Transaction.currentEntitlements` | `store.FetchPurchases()`, or `store.CheckEntitlement(product)` for one product |
|
|
299
|
+
| `SKPaymentQueue.canMakePayments()` | `store.AppleStoreExtendedService?.canMakePayments`, after `Connect()` |
|
|
300
|
+
| `SKReceiptRefreshRequest` | No equivalent; `store.FetchPurchases()` covers re-delivery |
|
|
301
|
+
| `SKStorefront` | `AppleStoreExtendedService.FetchStorefront` from package 5.2; not exposed in 5.0–5.1. Check the installed version's `xrefmap.yml` |
|
|
302
|
+
| `product.subscriptionPeriod` / `product.introductoryPrice` | `AppleStoreExtendedProductService.GetProductDetails()` / `GetIntroductoryPriceDictionary()` (raw JSON), or the `SubscriptionInfo` methods |
|
|
303
|
+
| `SKPaymentDiscount` (promotional offer), `winBackOffer` | **Not supported** — report as a hard blocker (Step 5) |
|
|
304
|
+
|
|
305
|
+
## Step 10 — Rollback Plan
|
|
306
|
+
|
|
307
|
+
- Wrap all new Unity IAP C# code in `#if USE_UNITY_IAP_V5`.
|
|
308
|
+
- Wrap all replaced native bridge calls (`[DllImport("__Internal")]` invocations) in `#if !USE_UNITY_IAP_V5`.
|
|
309
|
+
- ObjC/Swift plugin files cannot use C# defines — leave them in place untouched. The `#if` guards on the C# call sites prevent the bridge from being invoked.
|
|
310
|
+
- To revert: remove `USE_UNITY_IAP_V5` from **Edit > Project Settings > Player > Scripting Define Symbols**. The native StoreKit bridge is restored without any code changes.
|
|
311
|
+
- Never activate both purchase systems simultaneously — both register as `SKPaymentQueue` observers and will compete.
|
|
312
|
+
- Document the rollback steps in `IapMigrationNotes.md`.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Step 11 — Test Checklist
|
|
317
|
+
|
|
318
|
+
Include this in `IapMigrationNotes.md` after migration:
|
|
319
|
+
|
|
320
|
+
- [ ] Fresh install — products load and display prices
|
|
321
|
+
- [ ] Upgrade from old app version to migrated version — no duplicate entitlements
|
|
322
|
+
- [ ] Consumable purchase — content granted
|
|
323
|
+
- [ ] Repeat consumable purchase — repeatable, no block
|
|
324
|
+
- [ ] Non-consumable purchase — content granted once
|
|
325
|
+
- [ ] Non-consumable restore via "Restore Purchases" button — content restored on reinstall
|
|
326
|
+
- [ ] Subscription purchase — subscription active
|
|
327
|
+
- [ ] Subscription restore — status refreshed on launch
|
|
328
|
+
- [ ] Ask-to-Buy (deferred) — pending UI shown, no premature grant; purchase completes when parent approves
|
|
329
|
+
- [ ] Promotional purchase intercept (if applicable) — `OnPromotionalPurchaseIntercepted` fires, `ContinuePromotionalPurchases()` proceeds correctly
|
|
330
|
+
- [ ] Code redemption sheet (if applicable) — `PresentCodeRedemptionSheet()` opens
|
|
331
|
+
- [ ] Interrupted purchase flow — re-delivered on next launch via `OnPurchasePending`
|
|
332
|
+
- [ ] App killed during purchase — pending order re-delivered on next launch
|
|
333
|
+
- [ ] Backend validation success — entitlement granted (JWS payload accepted by backend)
|
|
334
|
+
- [ ] Backend validation failure — entitlement NOT granted, purchase not confirmed
|
|
335
|
+
- [ ] Network failure during validation — purchase left pending, re-delivered on next launch
|
|
336
|
+
- [ ] Sandbox tester account — no real charges, sandbox transactions process correctly
|
|
337
|
+
- [ ] TestFlight build — products load and sandbox purchases succeed
|
|
338
|
+
- [ ] App Store Connect product ID match — all IDs match exactly
|
|
339
|
+
- [ ] App Store Connect subscription group — base plan configuration compatible with Unity IAP
|
|
340
|
+
- [ ] No duplicate entitlement grant
|
|
341
|
+
- [ ] No unfinished transactions remaining (all purchases confirmed)
|
|
342
|
+
- [ ] No double grant of consumables
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Step 12 — 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 using the SK1 receipt bundle (base64 + `/verifyReceipt`)? If so, a backend migration to JWS validation is required.
|
|
352
|
+
3. Does the plugin intercept App Store promotional purchases (`paymentQueue:shouldAddStorePayment:forProduct:`)?
|
|
353
|
+
4. Are any subscriptions using promotional offer signing (`SKPaymentDiscount`)? If so, this is a hard blocker.
|
|
354
|
+
5. Should the skill preserve the old public C# billing API as a compatibility facade?
|
|
355
|
+
6. Should native ObjC/Swift plugin files be kept, disabled, or removed after migration validation?
|
|
356
|
+
|
|
357
|
+
If enough information can be inferred, proceed with a best-effort plan and mark uncertain items as **TODO**.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Implement Unity IAP D2C Capabilities (Third-Party Payment Provider)
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Trigger Phrases](#trigger-phrases)
|
|
6
|
+
- [Prerequisites (verify before any changes)](#prerequisites-verify-before-any-changes)
|
|
7
|
+
- [Step 1 — Project Scan](#step-1--project-scan)
|
|
8
|
+
- [Step 2 — Product Discovery](#step-2--product-discovery)
|
|
9
|
+
- [Step 3 — Deploy Catalog to Remote Catalog](#step-3--deploy-catalog-to-remote-catalog)
|
|
10
|
+
- [Step 4 — IAPManager with PaymentProvider](#step-4--iapmanager-with-paymentprovider)
|
|
11
|
+
- [Step 5 — Remote Catalog](#step-5--remote-catalog)
|
|
12
|
+
- [Step 6 — Deep Link Setup](#step-6--deep-link-setup)
|
|
13
|
+
- [Step 7 — Purchase Handling](#step-7--purchase-handling)
|
|
14
|
+
- [Step 8 — Product Type Behavior](#step-8--product-type-behavior)
|
|
15
|
+
- [Step 9 — Cloud Save Integration](#step-9--cloud-save-integration)
|
|
16
|
+
- [Step 10 — Verification Report](#step-10--verification-report)
|
|
17
|
+
- [Step 11 — Manual Steps (always include in report)](#step-11--manual-steps-always-include-in-report)
|
|
18
|
+
|
|
19
|
+
Use this reference when the user explicitly asks to add IAP D2C Capabilities (third-party payment provider such as Stripe or Coda) to a project. This path is valid only when the project has no IAP, or already has `com.unity.purchasing` v5.x installed.
|
|
20
|
+
|
|
21
|
+
**Not valid when:** the project has IAP v4, native Google Billing, or a third-party IAP package — resolve those first via the pre-check routing before returning to this path.
|
|
22
|
+
|
|
23
|
+
## Trigger Phrases
|
|
24
|
+
|
|
25
|
+
- "Add IAP D2C Capabilities"
|
|
26
|
+
- "Integrate Stripe / Coda payments"
|
|
27
|
+
- "Add third-party payment provider"
|
|
28
|
+
- "Set up web-based IAP checkout"
|
|
29
|
+
- "Add Unity payment provider"
|
|
30
|
+
|
|
31
|
+
## Prerequisites (verify before any changes)
|
|
32
|
+
|
|
33
|
+
1. Read the Prerequisites section of [Integrate D2C payment providers workflow](https://docs.unity.com/en-us/iap/payment-providers/workflow.md). It lists the minimum Editor version, the required package versions (`com.unity.purchasing`, Authentication, Core, Deployment) and the Unity Cloud setup.
|
|
34
|
+
2. Check each one against the project: the Editor version in `ProjectSettings/ProjectVersion.txt`, and the package versions in `Packages/packages-lock.json`.
|
|
35
|
+
3. If anything is missing, stop and list the missing items for the user before writing any code, because D2C fails at runtime, not at compile time, when a prerequisite is missing.
|
|
36
|
+
|
|
37
|
+
## Step 1 — Project Scan
|
|
38
|
+
|
|
39
|
+
Search the project for existing IAP and economy signals before writing any code.
|
|
40
|
+
|
|
41
|
+
### 1a — Existing IAP detection
|
|
42
|
+
|
|
43
|
+
Search `Packages/manifest.json` for `com.unity.purchasing`:
|
|
44
|
+
- If **v5.4+** found → proceed, IAP D2C Capabilities will be added alongside.
|
|
45
|
+
- If **v5.0–5.3** found → inform the user that v5.4+ is required, instruct them to upgrade `com.unity.purchasing` to v5.4+ via Package Manager, and continue once the upgrade is confirmed.
|
|
46
|
+
- If **absent** → proceed, IAP D2C Capabilities will be added fresh.
|
|
47
|
+
|
|
48
|
+
### 1b — Unity Authentication detection
|
|
49
|
+
|
|
50
|
+
Search `Packages/manifest.json` for `com.unity.services.authentication`. If absent, inform the user it must be installed — IAP D2C Capabilities will not initialize without a signed-in player.
|
|
51
|
+
|
|
52
|
+
### 1c — Inventory and economy scan
|
|
53
|
+
|
|
54
|
+
Search `Assets/**/*.cs` for:
|
|
55
|
+
```
|
|
56
|
+
\bcoins\b|\bgems\b|\blives\b|\binventory\b|\bcurrency\b
|
|
57
|
+
PlayerData|SaveAsync|CloudSave|SaveDataAsync|SaveGame
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 1d — Shop UI scan
|
|
61
|
+
|
|
62
|
+
Search `Assets/**/*.unity`, `*.prefab` for shop-related GameObjects and scripts:
|
|
63
|
+
```
|
|
64
|
+
Shop|Store|Purchase|Buy|IAP|Product
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Step 2 — Product Discovery
|
|
68
|
+
|
|
69
|
+
### If existing `.ucat` files are found
|
|
70
|
+
|
|
71
|
+
Locate `Assets/**/*.ucat` and `Assets/**/*.catalog.csv` files. Use them as-is (see [Catalog file formats](#catalog-file-formats)).
|
|
72
|
+
|
|
73
|
+
### If existing IAP 5 `ProductDefinition` objects are found
|
|
74
|
+
|
|
75
|
+
These are local store products — IAP D2C Capabilities uses a Remote Catalog instead. Inform the user that existing local product definitions need to be re-created as `.ucat` files deployed to Unity Cloud, and that product IDs (`uSKU`) should match the existing IDs to preserve store history.
|
|
76
|
+
|
|
77
|
+
### If no product definitions exist
|
|
78
|
+
|
|
79
|
+
**Stop and ask:**
|
|
80
|
+
|
|
81
|
+
> "Please provide the first IAP product ID and type — for example `com.mygame.coins100` as Consumable — and tell me which inventory field, currency, or item should be credited after purchase."
|
|
82
|
+
|
|
83
|
+
- Default to Consumable if type is not provided, but state the assumption explicitly.
|
|
84
|
+
- **If any Subscription products are provided or detected**, exclude them from the implementation and warn the user:
|
|
85
|
+
|
|
86
|
+
> "The following products were skipped because subscriptions are not supported by IAP D2C Capabilities in v5.4+: [list]. Only Consumable and NonConsumable products will be implemented."
|
|
87
|
+
|
|
88
|
+
Continue with the remaining Consumable and NonConsumable products. If no supported products remain after exclusion, stop and inform the user.
|
|
89
|
+
|
|
90
|
+
### Catalog file formats
|
|
91
|
+
|
|
92
|
+
D2C products are defined as `.ucat` files (one product per file) or a single `.catalog.csv` file under `Assets/`, not in code. Before creating or editing either format, read [Create your Remote Catalog](https://docs.unity.com/en-us/iap/payment-providers/configure-remote-catalog.md) for the fields, the CSV columns and the validation rules, and reread it if the Deployment window reports a validation error. Prefer one `.ucat` per product for a handful of products, and `.catalog.csv` when the user already keeps products in a spreadsheet.
|
|
93
|
+
|
|
94
|
+
Gotchas the agent must respect:
|
|
95
|
+
|
|
96
|
+
- **The `.ucat` filename drives identity.** `CatalogListingId` is always `"catalog/" + <filename-stem>` and is never written in the JSON. `uSKU` defaults to the filename stem, so omit `uSKU` from the JSON unless the store SKU must differ from the filename. Name files after the product ID so `coins_100.ucat` gives `uSKU = "coins_100"` and `CatalogListingId = "catalog/coins_100"`.
|
|
97
|
+
- **In `.catalog.csv`, a filled-in `CatalogListingId` must include the `catalog/` prefix.** Leave the column blank to derive it from `Sku`.
|
|
98
|
+
- **Prices are decimal major units** (`1.99`), not micros. The SDK converts them on upload.
|
|
99
|
+
- **`isWebshopAvailable` is a local toggle.** Turning it off and redeploying erases the server-side webshop data (`categories`, `hdImages`, `promotion`). Confirm with the user before turning it off on a deployed item.
|
|
100
|
+
- **Skip `Subscription` items**, as described above.
|
|
101
|
+
|
|
102
|
+
## Step 3 — Deploy Catalog to Remote Catalog
|
|
103
|
+
|
|
104
|
+
`.ucat` and `.catalog.csv` files are local definitions only. Until they are deployed to the Remote Catalog for the active Unity Cloud environment, `FetchRemoteCatalog()` returns no products and no purchase can start.
|
|
105
|
+
|
|
106
|
+
1. Follow the upload section of [Create your Remote Catalog](https://docs.unity.com/en-us/iap/payment-providers/configure-remote-catalog.md) to deploy the catalog files from the Deployment window. If the Deployment window is missing, the Deployment package isn't installed (see Prerequisites).
|
|
107
|
+
2. Check the environment in **Edit > Project Settings > Services > Environments**, because deployment targets the active environment and each environment has its own catalog.
|
|
108
|
+
3. If the user can't deploy yet (for example, no Unity Cloud access), list deployment as a manual step in the report and continue with the client code.
|
|
109
|
+
|
|
110
|
+
For environment configuration, project linking and multi-environment workflows, use the build-live-game skill.
|
|
111
|
+
|
|
112
|
+
## Step 4 — IAPManager with PaymentProvider
|
|
113
|
+
|
|
114
|
+
Read [Initialize Unity IAP](https://docs.unity.com/en-us/iap/set-up-in-app-purchasing.md) and [Initiate a purchase](https://docs.unity.com/en-us/iap/payment-providers/initiate-purchase.md) before writing the IAPManager, and reread them if a D2C call fails to compile or returns nothing.
|
|
115
|
+
|
|
116
|
+
### Initialization order
|
|
117
|
+
|
|
118
|
+
1. `await UnityServices.InitializeAsync()`.
|
|
119
|
+
2. Sign the player in with Unity Authentication. Don't use anonymous sign-in for D2C purchases, because an anonymous player who reinstalls or clears app data loses their purchase history. Use a persistent identity (a linked Unity Authentication account or the user's own identity provider), and ask the user which one if the project has none.
|
|
120
|
+
3. Only after sign-in succeeds, obtain `UnityIAPServices.StoreController(PaymentProvider.Name)` and call `Connect()`.
|
|
121
|
+
|
|
122
|
+
`PaymentProvider.Name` identifies the payment provider integration. It is not the provider's display name (Stripe or Coda).
|
|
123
|
+
|
|
124
|
+
### Payment provider services on the StoreController
|
|
125
|
+
|
|
126
|
+
The payment-provider APIs are on two properties of the `PaymentProvider.Name`-scoped `StoreController`. The names are asymmetric, and agents often swap them:
|
|
127
|
+
|
|
128
|
+
| Property | Interface | Holds |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| `store.PaymentProviderStoreExtendedService` (singular) | `IPaymentProvidersExtendedService` | eligibility, the Purchase Options UI, presentation modes, `SetDeepLinkScheme` |
|
|
131
|
+
| `store.PaymentProvidersExtendedPurchaseService` (plural) | `IPaymentProvidersExtendedPurchaseService` | `PurchaseProduct`, `RedirectToWebshop`, `GenerateURL`, `SetComplianceCheck`, `SetPaymentProviderOverride` |
|
|
132
|
+
|
|
133
|
+
Don't use `PurchaseService.PaymentProviders`, because it is a different entry point. Both properties are `null` on a `StoreController` scoped to Apple or Google, so guard with `?.` if the same code can see either kind of controller.
|
|
134
|
+
|
|
135
|
+
### Coexistence with existing Apple / Google StoreController
|
|
136
|
+
|
|
137
|
+
If the project already has a `StoreController` for Apple App Store or Google Play:
|
|
138
|
+
|
|
139
|
+
1. Create a new, separate `StoreController` scoped to `PaymentProvider.Name`. Never modify or replace the existing one, because the two manage different products on different billing backends.
|
|
140
|
+
2. After the new controller connects, ask the user:
|
|
141
|
+
|
|
142
|
+
> "An existing Apple/Google StoreController was found. Would you like to:
|
|
143
|
+
> - **Keep both** — run Apple/Google billing and IAP D2C Capabilities side by side (existing products stay on Apple/Google, new products use IAP D2C Capabilities)
|
|
144
|
+
> - **Remove the Apple/Google StoreController** — migrate fully to IAP D2C Capabilities (note: existing Apple/Google products and purchase history will no longer be managed by the app)"
|
|
145
|
+
|
|
146
|
+
3. If the user chooses **keep both**, leave the existing controller and its initialization untouched, and document the dual-controller setup in code comments.
|
|
147
|
+
4. If the user chooses **remove**, wrap the existing controller code in `#if !USE_IAP_D2C_ONLY` guards rather than deleting it, mark it `[Obsolete]`, and tell the user to retire the matching products in App Store Connect or the Play Console.
|
|
148
|
+
|
|
149
|
+
### Purchase entry point
|
|
150
|
+
|
|
151
|
+
Use the built-in Purchase Options UI (`ShowPurchaseOption(catalogListingId)`) as the purchase entry point, as [Initiate a purchase](https://docs.unity.com/en-us/iap/payment-providers/initiate-purchase.md) describes. Get the `IPaymentOptionProvider` once after `Connect()`, with `GetPaymentOptionProviderUGUI()` or `GetPaymentOptionProviderUITK(hostDocument)` to match the project's UI system.
|
|
152
|
+
|
|
153
|
+
Gotchas:
|
|
154
|
+
|
|
155
|
+
- Call `GetEligiblePaymentProviders()` after `Connect()` and gate the purchase UI on it. An empty `Providers` list means no routing rule matches the player or region. If `PaymentOptionPopupEnabled` is false, skip the picker, because the server has suppressed it.
|
|
156
|
+
- **Don't call `PurchaseProduct` on the D2C-scoped controller as a "native fallback".** It still routes through the payment provider. A native fallback needs a separate default `StoreController()`. Reuse the project's existing Apple/Google controller if there is one; in a D2C-only project, show a "payment unavailable" error instead.
|
|
157
|
+
- `ShowPurchaseOption(catalogListingId)` returns the player's choice: `IPaymentOptionProvider.NativeAlias` (`"native"`), `IPaymentOptionProvider.WebshopAlias` (`"webshop"`), a provider ID such as `"stripe"`, or `null` if the player dismissed the picker. Treat `null` as a cancel, not an error.
|
|
158
|
+
- **The SDK remembers each player's last provider on the device** and preselects it. If the picker seems to skip options, that's expected. During testing, clear app data to reset it, because there is no API to clear it.
|
|
159
|
+
|
|
160
|
+
### IAPManager responsibilities
|
|
161
|
+
|
|
162
|
+
Same as standard IAP 5 (see `path-add-iap-to-new-project.md` Step 4), with these additions:
|
|
163
|
+
- Hold the `PaymentProvider.Name`-scoped `StoreController` instance.
|
|
164
|
+
- Hold the `IPaymentOptionProvider` instance (UGUI or UI Toolkit, matching project's UI system).
|
|
165
|
+
- Expose `Buy(string catalogListingId)` — calls `ShowPurchaseOption(catalogListingId)` if eligible, and otherwise falls back to the native controller or reports that payment is unavailable.
|
|
166
|
+
- Expose `RestorePurchases()` only if NonConsumable products exist.
|
|
167
|
+
- Ensure `UnityServices.InitializeAsync()` and player sign-in both complete before `StoreController(PaymentProvider.Name)` is obtained and `Connect()` is called.
|
|
168
|
+
- Call `GetEligiblePaymentProviders()` after connect and use the result to gate purchase UI visibility.
|
|
169
|
+
- **Only automatic entitlement delivery is supported.** Do not implement server-authoritative grant logic in this path unless the user explicitly requests it.
|
|
170
|
+
|
|
171
|
+
## Step 5 — Remote Catalog
|
|
172
|
+
|
|
173
|
+
D2C products come from the Remote Catalog, not a local `List<ProductDefinition>`. Fetch them with `RemoteCatalogProvider`, as [Initialize Unity IAP](https://docs.unity.com/en-us/iap/set-up-in-app-purchasing.md) shows.
|
|
174
|
+
|
|
175
|
+
- Call `FetchRemoteCatalog()` after `Connect()` succeeds, then pass `catalogProvider.GetProducts()` to `store.FetchProducts()`.
|
|
176
|
+
- If the fetch result isn't successful, stop and surface the error, because every later step depends on the catalog.
|
|
177
|
+
- `FetchRemoteCatalog()` reads the catalog of the active environment. An empty result usually means the catalog wasn't deployed to that environment (Step 3).
|
|
178
|
+
- A product (uSKU) can have several catalog listings, for example regional or promotional offers. `product.catalogListings` is keyed by `catalogListingId`, and `GetProductByCatalogListingId(id)` returns the owning `Product`. Check `listing.availableToPurchase` before offering a listing. If every product has one listing, `GetProductById(uSKU)` is enough.
|
|
179
|
+
- For a custom shop UI, `product.metadata.GetPaymentProviderProductMetadata()` returns webshop fields (`hasWebshop`, `localizedWebshopPrice`, `webshopPriceString`). It returns `null` for products not fetched through the payment provider store.
|
|
180
|
+
- `PaymentProvidersExtendedPurchaseService.RedirectToWebshop(catalogListingId)` opens the webshop directly, without the picker. It runs the compliance callback first. Network failures throw on the returned `Task`, and a compliance rejection arrives through `OnPurchaseFailed`.
|
|
181
|
+
|
|
182
|
+
## Step 6 — Deep Link Setup
|
|
183
|
+
|
|
184
|
+
D2C checkout runs in a browser, which must redirect back to the game when payment completes. Read [Deep link success URL example](https://docs.unity.com/en-us/iap/payment-providers/success-deep-link.md) and the Unity Manual's [deep linking](https://docs.unity.com/en-us/engine/<VERSION>/manual/platform-specific/cross-platform-features/deep-linking.md) page and the platform page it links to before configuring it, and reread them if the redirect doesn't return to the app. In this Manual URL, replace `<VERSION>` with the major.minor of the Editor in `ProjectSettings/ProjectVersion.txt`, not the package version.
|
|
185
|
+
|
|
186
|
+
1. Ask the user:
|
|
187
|
+
|
|
188
|
+
> "What redirect URL did you configure in the Unity Cloud IAP payment provider dashboard? For example: `mygame://iapresult/okay`. If you haven't set one yet, set it in the dashboard first before continuing."
|
|
189
|
+
|
|
190
|
+
2. Prefer an app-scheme deep link (`mygame://...`) over an `https://` link, because `https://` links on Android need Google Digital Asset Links domain verification.
|
|
191
|
+
3. Call `store.PaymentProviderStoreExtendedService?.SetDeepLinkScheme("mygame")` **before** `Connect()`. Pass the scheme only, not the full URL, because the SDK matches incoming links against `<scheme>:` and a full URL never matches.
|
|
192
|
+
4. On Android, also declare the scheme and host in a custom `AndroidManifest.xml` intent filter, as the Manual's Android deep linking page describes, because `SetDeepLinkScheme` alone doesn't make the OS route the redirect to the app.
|
|
193
|
+
5. For production builds, recommend the proxy page from the success deep link example as the Success Redirect URL, because some devices drop a direct app-scheme redirect from a payment provider domain. The app-side setup stays the same.
|
|
194
|
+
|
|
195
|
+
In the Editor, the purchase callback arrives without a browser redirect, so no deep link setup is needed to test there.
|
|
196
|
+
|
|
197
|
+
If Android external link validation blocks dev or QA testing, the `IAP_SKIP_EXTERNAL_LINK_VALIDATION` scripting define bypasses it. Add it only to dev or QA builds and tell the user, because shipping it violates Google Play policies.
|
|
198
|
+
|
|
199
|
+
## Step 7 — Purchase Handling
|
|
200
|
+
|
|
201
|
+
Purchase handling follows the same save-before-confirm contract as standard IAP 5. See **Step 5 — Purchase Handling Contract** in `path-add-iap-to-new-project.md` for the full rules.
|
|
202
|
+
|
|
203
|
+
IAP D2C Capabilities-specific notes:
|
|
204
|
+
|
|
205
|
+
- **Checkout presentation mode:** leave the default, the external browser, unless the user asks for an in-app WebView. In that case call `store.PaymentProviderStoreExtendedService?.SetCheckoutPresentationMode(CheckoutPresentationMode.WebView)` before the purchase. With the external browser the game is suspended and resumes through the deep link. With WebView the game stays active. `OnPurchasePending` fires either way.
|
|
206
|
+
- **Webshop presentation mode is independent.** `RedirectToWebshop` uses `SetWebshopPresentationMode`, not the checkout mode, so setting checkout to WebView doesn't move the webshop into the WebView. If the user wants both in-app, set both.
|
|
207
|
+
- `OnPurchaseDeferred` fires if the payment is not immediately completed. Do not grant — show pending UI.
|
|
208
|
+
- Always confirm (`ConfirmPurchase`) only after entitlement is granted and saved. For consumables, Unity IAP D2C Capabilities prevents re-purchase until the previous order is confirmed.
|
|
209
|
+
|
|
210
|
+
### Apple and Google external purchase compliance
|
|
211
|
+
|
|
212
|
+
Apple and Google allow external web payments only in some regions and under their own program rules, and the developer, not Unity, is responsible for eligibility and disclosure. Read [Report transactions to Apple and Google](https://docs.unity.com/en-us/iap/payment-providers/external-purchase-compliance.md) before adding any compliance code, and ask the user which programs and regions they ship in, because the required flow depends on it.
|
|
213
|
+
|
|
214
|
+
Gotchas:
|
|
215
|
+
|
|
216
|
+
- `SetComplianceCheck` gates `PurchaseProduct` and `Purchase` only. It does **not** gate `GenerateURL`.
|
|
217
|
+
- Calling `GenerateURL` and then `PurchaseProduct` for the same listing reuses the same order, so disclosing the URL first doesn't double-charge.
|
|
218
|
+
- An order accepts at most two Apple/Google transaction tokens.
|
|
219
|
+
|
|
220
|
+
## Step 8 — Product Type Behavior
|
|
221
|
+
|
|
222
|
+
Same rules as standard IAP 5 (see `path-add-iap-to-new-project.md` Step 6), with one restriction:
|
|
223
|
+
|
|
224
|
+
**Subscriptions are not supported by IAP D2C Capabilities in v5.4+.** Skip any subscription products, warn the user which ones were excluded, and continue with Consumable and NonConsumable products only. Document excluded subscriptions as a TODO in the verification report for when subscription support is added.
|
|
225
|
+
|
|
226
|
+
## Step 9 — Cloud Save Integration
|
|
227
|
+
|
|
228
|
+
Same rules as standard IAP 5 — see `path-add-iap-to-new-project.md` Step 7. Save must complete before `ConfirmPurchase` is called.
|
|
229
|
+
|
|
230
|
+
## Step 10 — Verification Report
|
|
231
|
+
|
|
232
|
+
After applying changes, produce a report with these sections:
|
|
233
|
+
|
|
234
|
+
1. **Files changed** — list with nature of each change
|
|
235
|
+
2. **Product IDs, types, and `.ucat` files** — catalog summary
|
|
236
|
+
3. **Reward mapping** — product ID → field/method credited
|
|
237
|
+
4. **Deep link scheme configured** — scheme, host, AndroidManifest entry
|
|
238
|
+
5. **Save behavior** — which save method is called, when
|
|
239
|
+
6. **Restore behavior** — which products are restorable, how
|
|
240
|
+
7. **Pending / deferred handling** — confirmation of save-before-confirm and deferred UI
|
|
241
|
+
8. **Manual steps still required** — listed below
|
|
242
|
+
|
|
243
|
+
## Step 11 — Manual Steps (always include in report)
|
|
244
|
+
|
|
245
|
+
These happen in the Unity Dashboard or with third parties, so the agent can't do them. List each one in the report with a link to the section of [Integrate D2C payment providers workflow](https://docs.unity.com/en-us/iap/payment-providers/workflow.md) that explains it:
|
|
246
|
+
|
|
247
|
+
1. **Deploy the catalog** to the Remote Catalog (Step 3), if you couldn't.
|
|
248
|
+
2. **Connect a payment provider** (Stripe or Coda). Until then, the environment runs in [test mode](https://docs.unity.com/en-us/iap/payment-providers/test-mode.md).
|
|
249
|
+
3. **Set the redirect URLs** to match the deep link scheme you registered in Step 6.
|
|
250
|
+
4. **Choose purchase fulfillment**: SDK only, a webhook, or a Cloud Code module. Recommend server-side fulfillment for production.
|
|
251
|
+
5. **Add at least one routing rule** ([Add a routing rule](https://docs.unity.com/en-us/iap/payment-providers/routing.md)), because without one no player is offered a payment provider, even with a connected account.
|
|
252
|
+
6. **Confirm the active environment** in **Edit > Project Settings > Services > Environments** matches where the catalog was deployed.
|
|
253
|
+
7. **Review platform compliance** ([Report transactions to Apple and Google](https://docs.unity.com/en-us/iap/payment-providers/external-purchase-compliance.md)) and the provider's prohibited-business policy before shipping.
|