Unity切换分辨率后systemWidth/systemHeight未更新的解决方法求助
你通过ChangeDisplaySettingsEx成功切换了显示分辨率(将1920×1080转为1080×1920,旋转90度),但Unity的Display.systemWidth和systemHeight没有同步更新,这是因为Unity不会自动实时监听系统显示设置的变化,需要手动触发刷新或者通过正确的方式获取最新值。以下是几种可行的解决方法:
方法1:手动调用Display.ReloadDisplayStats()
Unity提供了Display.ReloadDisplayStats()方法,用来强制重新读取系统显示设备的状态,更新Display类的相关属性。你需要在调用ChangeDisplaySettingsEx之后,等待系统设置生效,再调用这个方法。
修改你的代码,添加等待和刷新逻辑:
DISP_CHANGE iRet = NativeMethods.ChangeDisplaySettingsEx( d.DeviceName, ref dm, IntPtr.Zero, DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero); // 确认显示设置切换成功后,强制刷新Unity显示数据 if(iRet == DISP_CHANGE.SUCCESSFUL) { Display.ReloadDisplayStats(); // 等待一帧确保Unity完成数据更新 yield return null; if (Display.displays.Length > 1) { UnityEngine.Debug.LogError(Display.displays[1].systemWidth + " " + Display.displays[1].systemHeight); UnityEngine.Debug.LogError(Display.displays[1].renderingWidth + " " + Display.displays[1].renderingHeight); } }
注意:这段代码需要在MonoBehaviour的协程中执行,因为yield return null需要协程环境。如果你的代码不在协程里,可以通过添加临时协程或延迟调用实现等待。
方法2:监听DisplayManager显示更新事件(Unity 2020+)
从Unity 2020版本开始,可通过DisplayManager的displaysUpdated事件监听显示设备变化,在回调中获取最新属性:
void Start() { // 注册显示更新事件 DisplayManager.displaysUpdated += OnDisplaysUpdated; } void OnDisplaysUpdated() { if (Display.displays.Length > 1) { UnityEngine.Debug.LogError(Display.displays[1].systemWidth + " " + Display.displays[1].systemHeight); UnityEngine.Debug.LogError(Display.displays[1].renderingWidth + " " + Display.displays[1].renderingHeight); } } void OnDestroy() { // 取消事件注册,避免内存泄漏 DisplayManager.displaysUpdated -= OnDisplaysUpdated; }
调用ChangeDisplaySettingsEx后,系统显示设置生效时会触发该事件,此时获取的Display属性即为最新值。
方法3:直接通过原生接口读取最新值
如果上述方法不生效,可在切换显示设置后,再次调用EnumDisplaySettings直接读取系统最新的分辨率,绕过Unity的Display缓存:
DISP_CHANGE iRet = NativeMethods.ChangeDisplaySettingsEx( d.DeviceName, ref dm, IntPtr.Zero, DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero); if(iRet == DISP_CHANGE.SUCCESSFUL) { // 重新读取系统最新显示设置 NativeMethods.EnumDisplaySettings(d.DeviceName, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm); int currentWidth = dm.dmPelsWidth; int currentHeight = dm.dmPelsHeight; UnityEngine.Debug.LogError("最新分辨率:" + currentWidth + " " + currentHeight); // 可选:手动同步Unity渲染分辨率 if (Display.displays.Length > 1) { Display.displays[1].SetRenderingResolution(currentWidth, currentHeight); } }
这种方式直接从系统获取数据,不受Unity缓存影响,还能手动对齐Unity的渲染分辨率。
注意事项
- 调用
ChangeDisplaySettingsEx后,系统需要短暂时间应用设置,不要立即读取值,需等待或通过返回值确认成功后再操作。 - 不同Unity版本对Display类的处理有差异,建议参考对应版本官方文档确认API可用性。
内容的提问来源于stack exchange,提问作者SoulSystem

