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,我们这也处理不了
只能从源头改起
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会有一个小盾牌,打开时会询问是否允许程序对设备进行修改