背景

写系统过程中不同分辨率浮动处理是经常遇到的问题。

在不同分辨率过程中可能会存在适配问题,手游关联居多,手游之前在Unity开发时已经写过一篇相关文章(UI手机适配 )。

此篇为对于UE引擎下端游适配问题的处理,可包括不同分辨率,带鱼屏等。

2D空间坐标

  • 窗口空间(window Space):程序运行时打开的窗口,此时的整个窗口坐标系(左上至右下)可以理解为Widget的窗口空间,如PIE模式下编辑器的视口,或者正式发布版本的游戏窗口。

v2-0f5f5a783fed635ec6768113acdba075_1440w

  • 屏幕空间(Monitor Space):显示输出设备的整个屏幕大小(左上至右下),如PC的显示器或者手机的屏幕输出。

    v2-98e9deb4a2df99981ff75d33e08bfaae_1440w

API

GetLocalSize() 相对大小,一般是由在编辑器内设置的大小决定(TileView组件的Item的大小会受TileView的Entry变量设置的大小影响)。

GetAbsoluteSize() 实际大小,包含对自适应各种分辨率情况下的DPI的设定。

LocalToViewport() 坐标转换,两个引用参数ViewportPosition(相对于父PanelWidget的位置) 和 PixelPosition(对于WindowSpace的位置);ViewportPosition一般使用时需获取父级含有CanvasSlot或者OverlaySlot的控件才可以调用SetPosition API,PixelPosition为相对于视口的绝对位置,已计算DPI,对于直接AddToViewport的Widget可以使用此数据计算实际需要显示在程序窗口的位置。

LocalToAbsolute() 返回相对于MonitorSpace的坐标(参考屏幕空间图)

Geometry的信息必须在Widget存在并有效的情况,否则会没有数据。另外因为实际数据会跟随tick更新,当调用GetCacheGeometry()API时不保证获取的信息是当前帧已经绘制好的最新的信息。所以UE推荐尽量通过改变Widget的层次结构来实现UMG的显示逻辑,只有在没办法的情况下才使用Geometry。

如文章标题所述,根据前面的介绍,我们可以通过GetViewportSize(),GetViewportScale() 分别获得当前程序视口的实际大小,以及应用在UE引擎中的DPI缩放值。

再通过GetAbsoluteSize(),LocalToViewport()的PixelPosition,分别获取需要动态控制的Widget的参照Widget的实际大小和视口位置。

而动态控制的目标Widget因为还没实际绘制在屏幕过,所以Geometry是没有数据的。此时计算位置时可能需要到的自身大小可以通过编辑器中设定的数值与DPI缩放值相乘,得到结果可以当作绘制时的大小。

通过上述条件的提供,根据需求即可动态计算目标Widget的实际位置,通过SetPositionInViewport()方法即可控制目标Widget的正确显示位置。

参考

UE中使用FGeometry动态控制Widget坐标 - 知乎

【UE·底层篇】Slate源码分析——点击事件的触发流程梳理 - 知乎