Skip to content

ScreenViewport 分辨率变化最佳实践 ​

ScreenViewport 描述客户端当前屏幕的物理尺寸、UI 逻辑尺寸、方向、设备像素比和安全区。分辨率适配代码应把它当作一次完整的 viewport 状态更新,而不是只监听 drawable 宽高。

选择事件 ​

优先订阅 ScreenViewport.Primary.OnViewportChanged:

csharp
#if CLIENT
using GameUI.Device;

private static void OnRegisterGameClass()
{
    var viewport = ScreenViewport.Primary;
    viewport.OnViewportChanged += RefreshLayout;
    Game.OnGameEnd += () => viewport.OnViewportChanged -= RefreshLayout;
}

private static void RefreshLayout()
{
    var viewport = ScreenViewport.Primary;
    var visibleSize = viewport.Size;
    var safeZone = viewport.SafeZonePadding;
    var orientation = viewport.DisplayOrientations;
    var devicePixelRatio = viewport.DevicePixelRatio;
    RebuildResponsiveLayout(visibleSize, safeZone, orientation, devicePixelRatio);
}
#endif

OnViewportChanged 在尺寸、方向、设备像素比、安全区和裁切偏移更新完成后触发。移动端 Surface 重建即使没有改变 drawable 宽高,也会通过该事件通知项目。OnSizeChanged 和 OnOrientationChanged 仍适合只关心单一维度的轻量逻辑,但不应单独作为完整响应式布局的唯一入口。

使用正确的坐标 ​

  • 普通 GameUI 布局使用 Size、DesignResolution 和控件的逻辑坐标,不要把 WidthPx / HeightPx 直接当作 UI 坐标。
  • WidthPx / HeightPx 是设备像素,适合截图、纹理、像素预算和底层诊断。
  • SafeZonePadding 是设备无关像素;可交互按钮、文字和重要 HUD 应避开安全区,背景和全屏装饰可以延伸到屏幕边缘。
  • GlobalOffsetPx 反映 CoverCentered 的裁切偏移。需要和物理像素坐标互转时,必须同时考虑 DevicePixelRatio。
  • 设计分辨率应从 ScreenViewport 或项目 GameDataGameUI 读取,不要硬编码某个手机或桌面分辨率。

避免重复和抖动 ​

窗口拖动、旋转和系统 UI 变化可能在短时间内产生多次通知。回调中只更新状态并标记布局脏,昂贵的图片重排、Canvas 重建或场景相机调整应合并到下一帧执行。不要在事件中递归修改窗口尺寸,也不要假定一次操作只产生一次回调。

如果界面会多次进入和退出,保存事件处理器并在对应生命周期结束时取消订阅,避免同一个布局被重复刷新。临时 UI 关闭后按控件生命周期调用 Destroy()。

旧客户端兼容 ​

同尺寸 Surface 重建通知属于客户端能力版本 4。项目通常可以直接订阅 OnViewportChanged;框架会对旧客户端保留实际尺寸变化的兼容路径。只有在项目必须区分两种实现时,才使用:

csharp
#if CLIENT
using GameCore.ClientEnvironment;

bool supportsSurfaceResize = ClientEnvironment.Runtime.Supports(
    ClientRuntimeFeature.ScreenViewportSurfaceResizeEvents);
#endif

不要用 BinaryVersion 或自行比较版本数字判断功能。未知能力版本按不支持处理。

Canvas 特别说明 ​

Canvas 开启 AutoUpdateResolutionOnResize 后,绘制分辨率会随控件尺寸自动调整;通常不需要在每次 viewport 通知中手动设置 Canvas.Resolution。如果项目确实要按像素预算调节 Canvas 质量,应在 OnViewportChanged 中读取最新的 WidthPx / HeightPx,计算目标分辨率,并合并连续通知。