Culture Shock

又被各民族迥异的文化震惊了,困扰我好几个月的神秘的bug。

起因是玩家报告说游戏启动之后画面特别的小,所有游戏场景都微缩在窗口正中,看不清也点不到,还有截图。并且有人说了之后,还有其他人附和。

我起初没特别在意,因为报这个错的人非常少,而且发帖的人不是English Native Speaker,甚至回帖的人都直接用德语在聊天。我还以为是来自欧洲的troll,想展示一下自己电脑分辨率特别高。但看起来又不像,毕竟他贴出来的分辨率还没有我的高……

因为没有头绪就不了了之了,直到几个月之后,有中文玩家开始报告同样的错误。这次就比较警觉了,我猜测是控制屏幕比例的代码有问题,读了好几遍觉得没啥逻辑错误。于是加了很多log,搞了个特殊版本,拜托玩家试试看。

结果虽然报bug的有那么几个,但是肯帮忙测还发log出来的就没有那么多了,毕竟不是人家的义务,我也只能等。过了好几天,终于有个热心玩家回馈了log文件,我看了好几遍,突然发现输入的“设计分辨率”参数居然变成了10倍!根据我设计的缩放逻辑,实际画面就被缩小到了1/10!

这下就搞了,为什么会出现这种问题?设计分辨率是储存在配置文件里的字符串啊……等等,我去翻了下配置,发现里面是这样写的:

[1920.0, 1080.0]

而log里面打印出来是这样的:

[19200,0, 10800,0]

这么多逗号是什么鬼?我突然想到了几个月前德国人发的帖子……等一下,莫非德国用的小数点是逗号?然后我就打开了c# fiddle,试了下这样的代码:

var cur = new CultureInfo("de");
Console.WriteLine("Hello World: " + float.Parse("1920.0",cur));

果然,1920.0被解析成了19200,整整翻了10倍……如果有人好奇的话,数字中的dot似乎被简单的忽略了。所以这个bug的成因是德语区的玩家因为本地的CultureInfo不同,解析字符串的时候会出错。

而之前的游戏没有错,是因为我储存了[1920,1080]这样的整数,后来编辑器修改,这部分以浮点数的形式输出了,就多了个小数点。看来信玩家的时间,应该也不是在中国,猜测是在欧洲生活的玩家就是了。

我也不知道为何Unity要去自动适应这种东西,可能是.NET的原因吧。目前的修复方法,强制在游戏的Start代码中加入

CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

这样至少保证主线程不适用本地的Culture,各种float.Parse和ToString就不用一个个去修改了。不幸中的万幸是,还好分辨率这关把玩家直接卡在了门外,要不然各种数值逻辑非得爆炸不可。

顺便记录下测试方法:需要在Windows10上修改显示语言,Setting/Language选项,添加新的语言,比如德语。然后再把显示语言修改为德语即可。不需要修改那个Unicode的东西,只要显示变了就会出bug,只能说.NET太商务了。

嗯嗯,奇怪的知识又增加了。