You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
    }
}

关键注意事项

  1. 避免空引用的核心:

    • 必须在OnInitialized回调完成后再访问商品,禁止在Start/Awake中直接调用商品获取逻辑。
    • 使用WithID而非WithStoreSpecificID:后者仅用于Unity配置ID与商店后台原始ID不一致的场景,绝大多数情况用WithID即可。
  2. 使用步骤:

    • 创建空GameObject,挂载该脚本。
    • 在Inspector中填入你的商品ID,并拖入用于显示价格的Text组件。
    • 若使用Unity自带的IAP Button,可将其On Click事件绑定到脚本的RefreshPriceOnClick方法,确保每次点击前刷新价格。
  3. 测试要求:

    • 必须在真实Android/iOS设备上测试,模拟器无法正确返回本地化价格。
    • 确保Unity IAP已配置对应商店的证书(Google Play的JSON文件、Apple的App Store Connect配置),且商品状态为激活。

内容的提问来源于stack exchange,提问作者qwdza54

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:20:17