记一个Unity关于无法读取本地时区的BUG

unity3d学习交流群913755380
先说个题外话,本地化经常会遇到很神奇的问题,记得不久前发现法国等国家,小数点用的是逗号

玩家反馈游戏卡住
查看收到的日志
发现报错

TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown.
  at System.TimeZoneInfo.FindSystemTimeZoneById (System.String id) [0x00039] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at System.TimeZoneInfo.CreateLocal () [0x00053] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at System.TimeZoneInfo.get_Local () [0x00009] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (System.DateTime time, System.Boolean& isAmbiguousLocalDst) [0x00000] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at System.DateTime.get_Now () [0x00008] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at UnityEngine.GUI..cctor () [0x00089] in <fe638f7e5d6c4d48bfcbaa0d553fa1b5>:0 
Rethrow as TypeInitializationException: The type initializer for 'UnityEngine.GUI' threw an exception.
  at UnityEngine.GUIUtility.ResetGlobalState () [0x00001] in <fe638f7e5d6c4d48bfcbaa0d553fa1b5>:0 
  at UnityEngine.GUIUtility.BeginGUI (System.Int32 skinMode, System.Int32 instanceID, System.Int32 useGUILayout) [0x0000d] in <fe638f7e5d6c4d48bfcbaa0d553fa1b5>:0 

这个是Unity封装的api,我们这也处理不了
只能从源头改起

这个论坛有人提供的复现方法,发现是Unity的问题

Aug 31, 2018

Reproduction steps:
1. Open "Regedit" -> "Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
2. Change "TimeZoneKeyName" value data to gibberish
3. Create a New or Open an existing Project
4. In the Editor log find error: "TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown."

Expected Result: Unity handles invalid "TimeZoneKeyName" registry values
Actual Result: "TimeZoneNotFoundException" errors are thrown when the "TimeZoneKeyName" registry value is invalid and the Editor/Build is unusable

Reproduced with: 2019.3.0b5, 2019.3.0b1, 2019.3.0a1, 2019.2.9f1, 2019.2.0a4, 2019.2.0a1, 2019.1.14f1, 2018.4.11f1, 2018.3.14f1, 2018.1.9f2
Did not reproduce on: 2020.1.0a8, 2019.3.0b6, 2017.4.33f1

注册表计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation 的key “TimeZoneKeyName”为无法读取的值时
c#调用 System.TimeZoneInfo.Local会报错
但是windows系统本身不受影响,时区也还是当前设置时区

DateTime.Now也会引用到System.TimeZoneInfo.Local
所以很容易导致游戏卡死

因此我们需要把TimeZoneKeyName改为可以正确读取的值

当然我们不能随便改玩家的时区,所以需要知道玩家当前系统是哪个时区的

C#无法调用System.TimeZoneInfo.Local 所以考虑用更底层的cmd来获取时区

tzutil /g
  try
        {
            System.TimeZoneInfo tzif = System.TimeZoneInfo.Local;
        }
        catch
        {

            using (System.Diagnostics.Process process = new System.Diagnostics.Process())
            {
                process.StartInfo.FileName = "tzutil";
                process.StartInfo.Arguments = "/g";
                // 必须禁用操作系统外壳程序,也就是不弹出cmd的黑框
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.Start();

                string output = process.StandardOutput.ReadToEnd();

                process.WaitForExit();
                process.Close();

                RegistryKey hklm = Registry.LocalMachine;
                RegistryKey software = hklm.OpenSubKey("SYSTEM", true);
                RegistryKey aimdir = software.OpenSubKey("CurrentControlSet\\Control\\TimeZoneInformation", true);

                aimdir.SetValue("TimeZoneKeyName", output);
                //aimdir.SetValue("TimeZoneKeyName", System.TimeZoneInfo.Local.Id);
            }
        }

最后还会遇到因为安全问题,没有权限修改注册表的问题
Unity打包发布PC程序之——默认管理员权限运行
可以通过这篇文章解决
这里简单的复述

注意改之前将要改的东西都备份下

找到Unity安装目录下的Editor\Data\PlaybackEngines\windowsstandalonesupport\Source\WindowsPlayer
打开WindowsPlayer.sln
找到WindowsPlayer.manifest
将权限等级level赋值为requireAdministrator
解决方案配置改为Release
ctrl+f5重构可执行文件模板
项目目录下build文件夹内会生成对应的exe,图标的右下角会有一个小盾牌
将其复制到Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations对应的目录下
win64_nondevelopment_mono为64位发布版本
win32_development_mono为32为开发版本
成功后,打包的exe会有一个小盾牌,打开时会询问是否允许程序对设备进行修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值