How to Setup IAP
Use this guide to add or configure an in-app purchase product. Based
directly on the project's IAPManager, which uses the current Unity IAP
v5 API (UnityIAPServices.StoreController(), package com.unity.purchasing
5.4.2, backed by Unity.Services.Core).
Architecture Context
IAPManager.Initialize()first callsUnityServices.InitializeAsync()with the environment name hardcoded to"production"— this codebase always talks to the real store backends, even from the Editor or a debug build; there's no separate sandbox environment switch here.- Products are not hardcoded in
IAPManager. They're data-driven fromShopProductIAPConfigScriptableObjectassets (underResources/ShopProductConfigs/IAP/), each carrying:ID— the store product ID. Must exactly match the product ID you registered in App Store Connect / Google Play Console, including case.Type— Unity IAP's ownProductTypeenum (Consumable,NonConsumable,Subscription). Must match what you registered on the store.Info,ProductType(the game's ownShopProductTypeenum —NoAds/ResourcesForAds/ResourcesRealMoney), andReward(a resource type + amount) — these only matter to the game's own shop logic; the store doesn't see or care about them.
GameConfig._shopProductIAPConfigsis a serialized array wired in the Inspector —GameConfigbuilds it into aShopProductsIAPMapdictionary keyed byIDat startup, and that dictionary is exactly whatIAPManager.InitializePurchasing()reads to build theProductDefinitionlist it fetches from the store. AShopProductIAPConfigasset that exists but isn't in this array is invisible to purchasing.IAPManager.GetPrice(productID)returns the store's own localized price string, populated onceOnProductsFetchedhas run — prices are never hardcoded.RestorePurchases()only runs an explicit restore flow onRuntimePlatform.IPhonePlayer(iOS); on other platforms it logs and no-ops, since Android purchases are restored automatically viaFetchPurchases()/OnPurchasesFetchedat init.
Pre-Setup Checklist
- A Unity Gaming Services project with In-App Purchasing enabled.
- Store-side setup done first: App Store Connect (iOS) and/or Google Play Console (Android) apps created, with the relevant banking/agreements in place — purchases can't complete without this, independent of any code change.
com.unity.purchasing(5.4.2) installed via the Package Manager.
Main Procedure
Step 1: Create the Product on the Store First
In App Store Connect / Google Play Console, create the in-app product or
subscription and note its exact product ID (reverse-DNS style, e.g.
com.yourcompany.yourgame.yourproduct) and whether it's Consumable,
Non-Consumable, or a Subscription.
Step 2: Create a Matching ShopProductIAPConfig Asset
In the Project window under Resources/ShopProductConfigs/IAP/, use
Create → Config → ShopProductIAPConfig and set:
ID— the exact store product ID from Step 1.Type— the matching Unity IAPProductType— must agree with what you registered on the store.Info/ProductType(game's own enum) /Reward— whatever your game's shop logic needs; these are internal to the game only.
Step 3: Register the Asset
Drag the new asset into GameConfig's _shopProductIAPConfigs array in
the Inspector. This step is easy to miss — an asset that exists on disk
but isn't in this array is never fetched.
Step 4: Wire the Purchase Button
Call IAPManager.OnPurchaseClicked(productID) with the same ID string
used in Step 2. Listen to ON_PRODUCT_PURCHASED, ON_PURCHASE_FAILED,
and ON_PURCHASE_PROCESS_COMPLETE to react to the result.
Step 5: Display the Price
Call IAPManager.GetPrice(productID) once products have been fetched —
don't show a shop screen before that, since it returns "0" until then.
Common Edit Recipes
Recipe A: Add a New Product
Steps 1–3 above, in order. No code changes are required —
IAPManager automatically picks up anything present in
GameConfig.ShopProductsIAPMap at init.
Recipe B: Change What a Product Rewards, Without Touching the Store
Edit the Reward / ProductType (game's own enum) fields on the
existing ShopProductIAPConfig asset. The store-side ID and Type
stay untouched, since the store has no concept of in-game rewards.
Troubleshooting
OnProductsFetchFailed, or a product never fetches. TheIDon the config asset doesn't exactly match the store product ID (check case), or the store-side product isn't yet in an approved/ready state.GetPrice()keeps returning"0". Called beforeOnProductsFetchedhas completed — gate your shop UI on that instead of assuming prices are available immediately afterInitialize().- Purchase button does nothing, logs "Not initialized". The store
controller hasn't connected yet, or
OnStoreDisconnectedfired — check_controller.GetConnectionState()before allowing purchase attempts. - New store product added, nothing happens in-game. Check it was
actually dragged into
GameConfig._shopProductIAPConfigs(Step 3) — a store product with no matching config asset in that array is never seen byIAPManager. - Restore Purchases seems to do nothing on Android. Expected —
RestorePurchases()only runs an explicit flow on iOS; Android restores automatically at init viaFetchPurchases().