Unity IAP获取商品价格含货币符号报错:空引用异常求助
Unity IAP 显示带货币符号的本地化价格解决方案
问题核心
空引用异常的根源通常是StoreController未初始化完成就访问商品,或者误用了商品ID匹配方法。直接使用product.metadata.localizedPriceString是正确方向,但需确保IAP初始化流程正确,且商品ID匹配无误。
可运行完整代码示例
以下脚本包含IAP初始化、商品获取、本地化价格更新的完整逻辑,可直接替代原有价格显示逻辑:
using UnityEngine; using UnityEngine.Purchasing; using UnityEngine.UI; public class IAPLocalizedPrice : MonoBehaviour, IStoreListener { private static IStoreController _storeController; private static IExtensionProvider _storeExtensionProvider; // 替换为你在Unity IAP配置中设置的商品ID [SerializeField] private string _targetProductId; [SerializeField] private Text _priceDisplayText; void Start() { InitializeIAP(); } private void InitializeIAP() { if (IsIAPInitialized()) { UpdatePriceDisplay(); return; } var configBuilder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance()); // 根据商品类型调整:Consumable(消耗品)/NonConsumable(非消耗品)/Subscription(订阅) configBuilder.AddProduct(_targetProductId, ProductType.Consumable); UnityPurchasing.Initialize(this, configBuilder); } private bool IsIAPInitialized() { return _storeController != null && _storeExtensionProvider != null; } // IAP初始化完成回调 public void OnInitialized(IStoreController controller, IExtensionProvider extensions) { _storeController = controller; _storeExtensionProvider = extensions; UpdatePriceDisplay(); } public void OnInitializeFailed(InitializationFailureReason error) { Debug.LogError($"IAP初始化失败: {error}"); _priceDisplayText.text = "加载失败"; } public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) { Debug.LogError($"购买失败: {product.definition.id}, 原因: {failureReason}"); } public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) { // 此处处理购买成功后的逻辑(如发放道具) Debug.Log($"购买完成: {args.purchasedProduct.definition.id}"); return PurchaseProcessingResult.Complete; } // 更新价格UI private void UpdatePriceDisplay() { if (!IsIAPInitialized()) { Debug.LogError("IAP控制器未初始化"); _priceDisplayText.text = "加载中..."; return; } // 用WithID匹配Unity IAP配置的商品ID,而非商店后台的原始ID Product targetProduct = _storeController.products.WithID(_targetProductId); if (targetProduct != null && targetProduct.availableToPurchase) { // 直接获取带货币符号的本地化价格字符串 _priceDisplayText.text = targetProduct.metadata.localizedPriceString; } else { Debug.LogError($"商品{_targetProductId}不存在或不可购买"); _priceDisplayText.text = "不可用"; } } // 可绑定到IAP Button的点击事件,确保刷新价格 public void RefreshPriceOnClick() { UpdatePriceDisplay(); } }
关键注意事项
避免空引用的核心:
- 必须在
OnInitialized回调完成后再访问商品,禁止在Start/Awake中直接调用商品获取逻辑。 - 使用
WithID而非WithStoreSpecificID:后者仅用于Unity配置ID与商店后台原始ID不一致的场景,绝大多数情况用WithID即可。
- 必须在
使用步骤:
- 创建空GameObject,挂载该脚本。
- 在Inspector中填入你的商品ID,并拖入用于显示价格的Text组件。
- 若使用Unity自带的IAP Button,可将其
On Click事件绑定到脚本的RefreshPriceOnClick方法,确保每次点击前刷新价格。
测试要求:
- 必须在真实Android/iOS设备上测试,模拟器无法正确返回本地化价格。
- 确保Unity IAP已配置对应商店的证书(Google Play的JSON文件、Apple的App Store Connect配置),且商品状态为激活。
内容的提问来源于stack exchange,提问作者qwdza54
相关产品推荐
相关产品推荐

