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

Unity C#嵌入iOS项目跨区域数字解析转换异常问题

问题背景

我有一个嵌入Unity场景作为视图的iOS项目,问题出现在系统本地化设置使用逗号,而非点号.作为小数分隔符的设备上。我从原生Swift代码向Unity发送参数字符串,Unity解析iOS传入的字符串后,生成新参数嵌入后续HTTP请求中。

异常日志

Xcode中获取的故障设备日志如下:

param from iOS: 615d48538edef900126a784e***616957b6f59835001137ae7b***98.42519685039369***100.06561679790026
Request Object:
- distanceFromCeiling: 9,84251968503937E+15
- distanceFromSideWall: 1,000656167979E+16
  - Obj: : UpdateRequest
  - Obj.distanceFromCeiling: : 9,84251968503937E+15
  - Obj.distanceFromSideWall: : 1,000656167979E+16
DATA request {"distanceFromCeiling":9842519685039368.0,"distanceFromSideWall":10006561679790026.0}

预期发送的参数为98.42519685039369, 100.06561679790026,但实际请求JSON中的数值变为了9842519685039368.0, 10006561679790026.0,使用en-US本地化的设备无此问题。

可疑代码

Unity侧代码如下,is_the_problem_here注释标记了可疑位置:

using System;
using System.Collections;
using System.Collections.Generic;
using Lean.Touch;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using UnityEngine.UIElements;

public class GameManager : MonoBehaviour
{

// 其他函数
// ====================================

void callApiFromIOS(string param)
{
    Debug.Log("param from iOS: " + param);

    string[] str = param.Split(new string[] { "***" }, StringSplitOptions.None);

    // is_the_problem_here
    System.Nullable <double> distanceFromCeiling = null;
    System.Nullable<double> distanceFromSideWall = null;

    if (str != null && str.Length >= 4)
    {
        string ceiling = str[2];
        if (!ceiling.Equals("null"))
        {
            // is_the_problem_here
            distanceFromCeiling = Convert.ToDouble(ceiling);
        }
       
        string sideWall = str[3];
        if (!sideWall.Equals("null"))
        {
            // is_the_problem_here
            distanceFromSideWall = Convert.ToDouble(sideWall);
        }
    }

    Debug.Log("Request Object: ");
    Debug.Log("- distanceFromCeiling: " + distanceFromCeiling);
    Debug.Log("- distanceFromSideWall: " + distanceFromSideWall);

    UpdateRequest updateRequest = new UpdateRequest(distanceFromCeiling, distanceFromSideWall);
    Debug.Log("  - Obj: : " + updateRequest);
    Debug.Log("  - Obj.distanceFromCeiling: : " + updateRequest.distanceFromCeiling);
    Debug.Log("  - Obj.distanceFromSideWall: : " + updateRequest.distanceFromSideWall);

    // is_the_problem_here
    string data = JsonConvert.SerializeObject(updateRequest);

    Debug.Log("DATA request " + data);

     // 剩余代码为将JSON数据设为请求体并发送HTTP请求
}

正常设备日志如下:

param from iOS: 615d48538edef900126a784e***616957b6f59835001137ae7b***98.42519685039369***100.06561679790026

Request Object: 
- distanceFromCeiling: 98.4251968503937
- distanceFromSideWall: 100.0656167979
  - Obj: : UpdateRequest
  - Obj.distanceFromCeiling: : 98.4251968503937
  - Obj.distanceFromSideWall: : 100.0656167979
DATA request {"distanceFromCeiling":98.425196850393689,"distanceFromSideWall":100.06561679790026}

尝试过的无效方案

我尝试自定义Json序列化转换器修改小数输出格式,未达到预期效果,输出仍和错误日志一致:

var converter = new FormattedDecimalConverter(CultureInfo.GetCultureInfo("en-US"));
string data = JsonConvert.SerializeObject(updateRequest, converter);

转换器类代码:

using System;
using System.Globalization;
using Newtonsoft.Json;

internal class FormattedDecimalConverter : JsonConverter
{
    private CultureInfo culture;

    public FormattedDecimalConverter(CultureInfo culture)
    {
        this.culture = culture;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(Convert.ToString(value, culture));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

解决方案

问题根源是区域本地化解析规则差异:Convert.ToDouble默认使用当前设备的区域设置解析字符串,在使用逗号作为小数分隔符的区域,会把输入字符串中的点号识别为千位分隔符,最终解析出错误的超大数值。
修复方法是将Convert.ToDouble()替换为指定固定区域格式的解析方法:

// 替换前
distanceFromCeiling = Convert.ToDouble(ceiling);
distanceFromSideWall = Convert.ToDouble(sideWall);

// 替换后
distanceFromCeiling = double.Parse(ceiling, CultureInfo.InvariantCulture);
distanceFromSideWall = double.Parse(sideWall, CultureInfo.InvariantCulture);

使用CultureInfo.InvariantCulture可以保证无论设备区域如何设置,都会按点号作为小数分隔符的规则解析字符串。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:45:07