多分辨率
多分辨率问题
开发人员经常会遇到麻烦,不知道如何在他们的游戏中最好地支持多种分辨率.对于桌面和控制台游戏,这或多或少是简单的,因为大多数屏幕长宽比是16:9,分辨率是标准的720p、1080p、1440p、4K,…….
对于手机游戏来说,起初,这很容易.许多年来,iPhone和iPad使用相同的分辨率.当实行 Retina 后,他们只是将像素密度提高了一倍;大多数开发商不得不以默认和双倍的分辨率提供资产.
如今,情况已不再如此,因为有很多不同的屏幕尺寸、密度和长宽比.非传统的尺寸也越来越受欢迎,如超宽显示屏.
对于3D游戏来说,没有太大的必要支持多种分辨率(从审美角度来看).3D几何图形将根据视场填充屏幕,而不考虑长宽比.在这种情况下,人们可能想要支持的主要原因是为了 性能 的原因(以较低的分辨率运行以增加每秒的帧数).
对于2D和游戏UI,这是一个不同的问题,因为设计需要在Photoshop、GIMP或Krita等软件中使用特定的像素尺寸来创建.
由于布局、长宽比、分辨率和像素密度会有很大的变化,因此不再可能为每个特定的屏幕设计UI.必须使用另一种方法.
万全之策
最常见的方法是使用一个单一的 基础 分辨率,然后将其适用于其他所有情况.这个分辨率是大多数玩家预期的玩游戏的方式,鉴于他们的硬件.对于移动设备,谷歌在网上有有用的 `统计资料<https://developer.android.com/about/dashboards>`__ ,对于桌面设备,Steam `也有<https://store.steampowered.com/hwsurvey/>`__ .
举个例子,Steam显示最常见的 主要显示分辨率是 1920×1080,所以明智的做法是为这个分辨率开发一个游戏,然后处理不同尺寸和长宽比的缩放.
Godot 还提供了一系列通用的容器.
基本大小
窗口的基本尺寸可以在项目设置中的 Display → Window 下指定.
然而,它的作用并不完全明显; 引擎将 不 尝试将显示器切换到此分辨率. 相反,将此设置视为”设计大小”,即您在编辑器中使用的区域的大小. 此设置直接对应于2D编辑器中蓝色矩形的大小.
通常需要支持具有与该基本大小不同的屏幕和窗口大小的设备. Godot提供了许多方法来控制视区的大小调整和拉伸到不同的屏幕大小.
注解
Godot遵循了现代多种分辨率的方法.引擎永远不会自行改变显示器的分辨率.虽然改变显示器的分辨率是最有效的方法,但这也是最不可靠的方法,因为如果游戏崩溃,它可能会让显示器卡在一个低分辨率上.这在macOS或Linux上很常见,因为它们对分辨率变化的处理不如Windows.
更改显示器的分辨率还会取消游戏开发者对过滤和纵横比拉伸的控制,这对于确保像素游戏的正确显示画面非常重要.
最重要的是,更改显示器的分辨率会使游戏的Alt-Tab键切换速度变慢,因为每次切换时显示器都必须更改分辨率.
调整大小
市面上有着各种各样的设备, 拥有各种类型的屏幕, 依次有着不同的像素密度和分辨率.处理所有的类型工作量巨大, 所以Godot试图让开发者的生活变得更简单. Viewport 节点提供了几个处理大小调整的函数, 而场景树的根节点始终是一个Viewport (场景将作为它的子节点被实例化, 并且始终可以通过调用 get_tree().get_root()
或 get_node("/root")
来访问它.
在任何情况下, 虽然更改 根视区
的参数可能是解决问题的最灵活方法, 但这样做的可能包含大量工作、大量代码和大量推测过程, 因此Godot在 项目设置
中提供了一组简单的参数来处理多分辨率问题.
拉伸设置
拉伸设置位于项目设置中,提供了几个选项:
拉伸模式 (Stretch mode)
Stretch Mode 设置定义了基本尺寸如何被伸展以适应窗口或屏幕的分辨率.
下面的动画使用仅16×9像素的”基本大小”来演示不同拉伸模式的效果. 单个精灵,大小也是16×9像素,覆盖整个视区,并在其上添加一个对角线 Line2D :
Stretch Mode = Disabled (默认).不发生拉伸.场景中的一个单位对应于屏幕上的一个像素.在这种模式下, Stretch Aspect 设置没有效果.
如果您想要完全控制每个屏幕像素,这是一个不错的选择,并且可能是3D游戏的最佳选择.
Stretch Mode = 2D: 在这种模式下,项目设置中的display/width和display/height所指定的尺寸被拉伸到覆盖整个屏幕(考虑到 Stretch Aspect 设置).这意味着所有的东西都直接在目标分辨率下进行渲染.3D基本上不受影响,而在2D中,精灵像素和屏幕像素之间不再有1:1的对应关系,这可能会导致缩放的伪影.
如果您的2D图稿具有足够高的分辨率并且不需要像素完美渲染,那么这是一个不错的选择. 考虑在2D纹理和字体上启用纹理过滤和mipmapping.
Stretch Mode = Viewport: 视窗缩放意味着根 Viewport 的尺寸被精确地设置为在项目设置的 Display 部分指定的基本尺寸.场景首先被渲染到这个视窗.最后,这个视窗被缩放以适应屏幕(考虑 Stretch Aspect 的设置).
在精确处理像素的游戏或者为了渲染到较低的分辨率以提高性能时,这种模式很有用.
拉伸比例(Stretch aspect)
第二个设置是拉伸纵横比.请注意,只有在 Stretch Mode 被设置为 Disabled 以外的情况下,这才会生效.
在下面的动画中,您会注意到灰色和黑色区域. 黑色区域由引擎添加,无法绘制. 灰色区域是场景的一部分,可以绘制. 灰色区域对应于您在2D编辑器中看到的蓝色框架外的区域.
Stretch Aspect = Ignore: 在拉伸屏幕时忽略长宽比.这意味着原始分辨率将被拉伸以完全填满屏幕,即使它更宽或更窄.这可能会导致不均匀的拉伸,事物看起来比设计的更宽或更高.
Stretch Aspect = Keep: 在拉伸屏幕的时候保持长宽比.这意味着无论屏幕分辨率如何,视窗都会保留原来的尺寸,黑条会被添加到屏幕的顶部或底部(“宽屏模式”)或侧面(“竖屏模式”).
如果您事先知道目标设备的宽高比,或者您不想处理不同的宽高比,这是一个不错的选择.
Stretch Aspect = Keep Width: 在拉伸屏幕时保持长宽比.如果屏幕比基本尺寸宽,则会在左右两边添加黑条(竖屏模式).但如果屏幕比基本分辨率高,视窗将在垂直方向上增长(更多的内容将在底部可见).你也可以把它看作是 “垂直扩展” .
这通常是创建可扩展的GUI或HUD的最佳选择,因此一些控件可以锚定到底部( 大小和锚定点).
Stretch Aspect = Keep Height: 在拉伸屏幕时保持长宽比.如果屏幕比基本尺寸高,则会在顶部和底部添加黑条(宽屏模式).但如果屏幕比基本分辨率宽,视窗将在水平方向上增长(更多的内容将在右边可见).你也可以把它看作是 “水平扩展” .
这通常是水平滚动的2D游戏的最佳选择(如跑步者或平台游戏者).
Stretch Aspect = Expand: 在拉伸屏幕时保持长宽比,但既不保持基本宽度也不保持高度.根据屏幕的长宽比,视窗将在水平方向(如果屏幕比基本尺寸宽)或垂直方向上变大(如果屏幕比原始尺寸高).
小技巧
To support both portrait and landscape mode with a similar automatically determined scale factor, set your project’s base resolution to be a square (1:1 aspect ratio) instead of a rectangle. For instance, if you wish to design for 1280×720 as the base resolution but wish to support both portrait and landscape mode, use 720×720 as the project’s base window size in the Project Settings.
To allow the user to choose their preferred screen orientation at run-time, remember to set Display > Window > Handheld > Orientation to sensor
.
拉伸收缩
Shrink 设置允许你在上面的 Stretch 选项已经提供的基础上增加一个额外的缩放系数.默认值为1意味着不发生缩放.
例如,如果你将 Shrink 设置为4,并将 Stretch Mode 置于 Disabled 状态,那么你的场景中的每个单元将对应于屏幕上的4×4像素.
如果 Stretch Mode 被设置为除 Disabled 之外的其他参数,根视窗的大小就会按 Shrink 的系数缩减,而输出中的像素则按相同的量放大.这对2D游戏很少有用,但可以通过在较低的分辨率下渲染来提高3D游戏的性能.
来自脚本
要在运行时从脚本中配置拉伸,请使用 get_tree().set_screen_stretch()
方法(见 SceneTree.set_screen_stretch() ).
减少缩减取样的混叠
如果游戏的基本分辨率很高(如3840×2160),当采样降到相当低的分辨率(如1280×720)时,可能会出现锯齿.可以通过在加载时将所有图像缩小2倍来减少锯齿的出现.这可以通过在加载游戏数据之前调用下面的方法来实现:
VisualServer.texture_set_shrink_all_x2_on_set_data(true)
或者,也可以在所有2D纹理上启用mipmap.然而,启用mipmap会增加内存的使用量,这个在低端移动设备上可能会出现问题.
处理纵横比
一旦考虑到不同分辨率的缩放,请确保你的 user interface 也能为不同的长宽比进行缩放.这可以使用 anchors 和/或 containers 来完成.
视场角(Field of view)缩放
3D相机节点的 Keep Aspect 属性默认为 Keep Height 缩放模式(也称为 Hor+ ).在横屏模式下,这通常是桌面游戏和手机游戏的最佳选择,因为宽屏显示器会自动使用更宽的视野.
然而,如果您的3D游戏打算使用纵向模式,那么使用 Keep Width保持宽度 称为( Vert- )可能会更有意义.这样,宽高比大于16:9(例如19:9)的智能手机将使用 更高 的视野,这在这里更符合逻辑.
使用视图端口以不同的方式缩放 2D 和 3D 元素
使用多个视图窗口节点,可以对不同的元素使用不同的比例.例如,您可以使用此选项以低分辨率渲染3D世界,同时将2D元素保持在原生分辨率.这可以显著提高性能,同时保持HUD和其他2D元素的清晰度.
这是通过只对2D元素使用根Viewport节点,然后创建一个Viewport节点来显示3D世界并使用ViewportContainer或TextureRect节点来实现的.最终项目中实际上将有两个视图窗口.与ViewportContainer相比,使用TextureRect的一个好处是它允许启用线性过滤.这使得缩放的3D视图窗口在许多情况下看起来更好.
有关示例,请参见 3D视窗缩放演示 .