From package-guide
This skill should be used when the user asks to "add IAP", "implement in-app purchase", "add gem purchase", "create shop system", "integrate Unity Purchasing", "add consumable products", or needs to implement any in-app purchase system in a Unity project. Provides a complete implementation workflow for Unity IAP with clean architecture patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/package-guide:unity-iapThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement a Unity IAP (In-App Purchase) system for consumable products using Unity Purchasing package.
Implement a Unity IAP (In-App Purchase) system for consumable products using Unity Purchasing package. The architecture follows a clean separation pattern: a thin wrapper service handles platform communication, a ScriptableObject catalog defines products, and decoupled events handle UI communication.
UI (ShopPopup)
|
|-- [Purchase button click] --> Event: PurchaseRequested(productId)
|
IAPService (MonoBehaviour + IDetailedStoreListener)
|
|-- [Platform purchase flow]
|-- [Receipt validation]
|-- [Grant reward] --> CurrencyVariable += amount
|-- [Broadcast result] --> Event: PurchaseCompleted / PurchaseFailed
|
UI (ShopPopup)
|-- [Result event received] --> Update UI
Key Principles:
Add com.unity.purchasing via Package Manager or manifest.json.
IAPProductEntry - Serializable data class per product:
[Serializable]
public class IAPProductEntry
{
public string ProductId; // Must match store console ID
public int RewardAmount; // Currency amount to grant
public Sprite Icon; // Optional: for shop UI
}
IAPProductCatalog - ScriptableObject holding all products:
[CreateAssetMenu(menuName = "IAP/Product Catalog")]
public class IAPProductCatalog : ScriptableObject
{
public List<IAPProductEntry> Products = new();
public int GetRewardAmount(string productId)
{
return Products.Find(p => p.ProductId == productId)?.RewardAmount ?? 0;
}
}
Implement IDetailedStoreListener with this lifecycle:
Awake() - DontDestroyOnLoad(gameObject)Start() - InitializePurchasing() using ConfigurationBuilderOnEnable() - Subscribe to purchase request eventOnDisable() - Unsubscribe from purchase request eventCritical methods:
InitializePurchasing() - Register products from catalog, call UnityPurchasing.Initialize(this, builder)HandlePurchaseRequest(string productId) - Validate state, call _storeController.InitiatePurchase(product)ProcessPurchase(PurchaseEventArgs) - Validate receipt, grant reward, broadcast successOnPurchaseFailed(Product, PurchaseFailureDescription) - Broadcast failureprivate bool ValidateReceipt(string receipt)
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
var validator = new CrossPlatformValidator(
GooglePlayTangle.Data(), null, Application.identifier);
validator.Validate(receipt);
return true;
}
catch (IAPSecurityException) { return false; }
#else
return true;
#endif
}
Pre-release requirement: Generate GooglePlayTangle.cs via:
Window > Unity IAP > IAP Receipt Validation Obfuscator
The shop UI should:
purchaseRequestEvent.Raise(productId) on button clickIAPService.GetLocalizedPrice(productId) for price displayAdd Unity.Purchasing.SecurityStub reference to the main asmdef for Editor compatibility
with Obfuscator/CrossPlatformValidator classes.
After implementation, generate a setup guide documenting:
Create ScriptableEvent<string> subclasses for purchase events. See references/implementation-patterns.md.
Use C# events or UnityEvent:
public static event Action<string> OnPurchaseRequested;
public static event Action<string> OnPurchaseCompleted;
public static event Action<string> OnPurchaseFailed;
| Pitfall | Solution |
|---|---|
Obfuscator not found in Editor | Add Unity.Purchasing.SecurityStub asmdef reference |
AppleTangle missing | Pass null to CrossPlatformValidator if Apple not targeted |
| Sirenix errors in test asmdef | Add Sirenix DLLs to precompiledReferences when overrideReferences: true |
| Pending purchases lost | Return PurchaseProcessingResult.Complete only AFTER granting reward |
| Price shows empty | GetLocalizedPrice() only works after OnInitialized callback |
references/implementation-patterns.md - Complete code templates with SOAP and non-SOAP variantsnpx claudepluginhub flashwade03/unity-dev-vibecoding-with-awesome-assets --plugin package-guideGame monetization strategies, in-app purchases, battle passes, ads integration, and player retention mechanics. Ethical monetization that respects players.
Unity 6 packages and services guide. Use when working with Package Manager, installing/updating packages, scoped registries, or Unity Gaming Services (Authentication, Cloud Save, Analytics, Leaderboards, Matchmaker). Covers essential packages list and version compatibility. Based on Unity 6.3 LTS documentation.
Implements StoreKit 2 in-app purchases, subscriptions, consumables, non-consumables, and transactions with .storekit testing workflow, StoreManager architecture, and verification.