跳到主要内容

屏幕

屏幕是界面根节点,即带有 Screen 组件的实体。其下的元素在屏幕定义的空间中布局。屏幕决定界面覆盖摄像机视图还是放在场景中、单位的含义,以及如何随画布缩放。

屏幕空间与世界空间​

透视场景中的立体面板,以及叠加在视图上的扁平 HUD、状态条和按钮

屏幕空间界面始终覆盖摄像机视图,与摄像机位置无关,大小始终等于画布。适用于 HUD、菜单及其他属于屏幕而非世界的界面。

世界空间界面通过实体变换放置在场景中,与其他场景内容一起绘制,例如墙上标牌、机器上方的面板或 XR 菜单。尺寸由 resolution 定义,使用实体局部单位,并以实体为中心。详见世界空间界面。

// Drawn over the camera's view, the size of the canvas
const hud = new pc.Entity('hud');
hud.addComponent('screen', {
screenSpace: true,
scaleMode: pc.SCALEMODE_BLEND,
referenceResolution: [1280, 720]
});
app.root.addChild(hud);

// Placed in the scene: 640 × 320 units, scaled to 6.4 × 3.2 meters
const sign = new pc.Entity('sign');
sign.addComponent('screen', {
screenSpace: false,
resolution: [640, 320]
});
sign.setLocalScale(0.01, 0.01, 0.01);
sign.setPosition(0, 2, -5);
app.root.addChild(sign);

两种屏幕使用相同元素和布局规则。

单位与分辨率​

元素使用屏幕单位定位和设置尺寸,Y 轴向上。一个单位的含义取决于屏幕:

屏幕分辨率一个单位等于
屏幕空间,Scale Mode 为 None画布绘制缓冲区尺寸,随画布尺寸变化而更新绘制缓冲区中的一个像素
屏幕空间,Scale Mode 为 Blend同上绘制缓冲区中的 scale 个像素,详见 Blend 缩放
世界空间设置的 resolution,默认为 640 × 320实体局部空间中的一个单位

屏幕空间屏幕自行设置分辨率,因此写入 resolution 不生效。画布尺寸变化时,锚定屏幕边缘和角落的元素也会随之移动。

Blend 缩放​

Scale Mode 为 None 时,界面按像素构建并保持像素尺寸,因此换到更大画布会显得很小,换到更小画布会溢出。使用 Blend 时,按参考分辨率设计界面,屏幕会将其缩放到实际画布,使比例保持一致:

相同界面在大小画布上的效果:None 在小画布溢出、在大画布偏小,Blend 则在两者中按比例缩放

const screen = new pc.Entity('screen');
screen.addComponent('screen', {
screenSpace: true,
scaleMode: pc.SCALEMODE_BLEND,
referenceResolution: [1280, 720],
scaleBlend: 0.5
});
app.root.addChild(screen);

需要修改参考分辨率时,为 referenceResolution 赋予新的 pc.Vec2。

屏幕分别比较画布与参考分辨率的两个轴,再由 Scale Blend 加权:

缩放 = (宽度 / 参考宽度) ^ (1 - 缩放混合) × (高度 / 参考高度) ^ 缩放混合

参考分辨率为 1280 × 720 时,1920 × 1080 画布的缩放为 1.5,640 × 360 为 0.5,与 Scale Blend 无关,因为宽高比例相同。只有画布形状不同时,Scale Blend 才会影响结果。当前缩放系数保存在 scale 中。

Scale Mode 仅适用于屏幕空间。世界空间屏幕不使用此缩放,应通过实体缩放调整。

选择缩放混合值​

Scale Blend 决定界面跟随画布哪个维度缩放:

Scale Blend缩放依据适合
0画布宽度竖屏布局,以及必须横向完整容纳的界面
0.5宽高等权重同时支持横竖屏;手机旋转不会改变缩放
1画布高度HUD 必须完整容纳在上下边界之间的横屏游戏

不同 Scale Blend 的横竖屏效果:0 在竖屏时适应宽度,0.5 保持横屏尺寸,1 则可能过宽

取 0.5 时,缩放仅取决于画布面积,因此旋转手机后界面尺寸不变;但按横屏参考分辨率设计的布局可能超出竖屏宽度。要始终完整显示参考区域,应选择空间更紧张的轴作为依据,并在画布尺寸变化时重新计算:

// Follow whichever axis has less room, so the whole reference area stays on screen
const fitReference = () => {
const { resolution, referenceResolution } = screen.screen;
const wider = resolution.x / referenceResolution.x > resolution.y / referenceResolution.y;
screen.screen.scaleBlend = wider ? 1 : 0;
};
fitReference();
app.graphicsDevice.on('resizecanvas', fitReference);
屏幕缩放

像素比​

高像素密度屏幕上,画布绘制缓冲区的像素数可多于页面中的 CSS 像素数,画面更清晰,但绘制成本也更高。图形设备的 maxPixelRatio 限制两者比例,不同开发方式的默认设置如下:

开发方式默认绘制缓冲区
引擎与画布 CSS 尺寸相同,因为 maxPixelRatio 为 1。将 app.graphicsDevice.maxPixelRatio 设为 window.devicePixelRatio 可使用完整分辨率
编辑器默认采用 CSS 尺寸;在渲染设置启用 Device Pixel Ratio 后使用设备完整像素比
React采用 CSS 尺寸。通过 useApp() 获取应用后,设置其图形设备的 maxPixelRatio
Web Components使用设备完整像素比,可通过 <pc-app> 的 max-pixel-ratio 限制

像素比对两种缩放模式的影响不同:

  • Blend:分辨率与缩放系数同步增大,因此页面上的界面尺寸不变,只变得更清晰。
  • None:一个单位对应一个绘制缓冲像素,因此像素比越高,界面越小。例如像素比为 2 时,100 单位宽的按钮只有 50 CSS 像素宽。

像素精确图像​

Scale Mode 为 None,且图像元素尺寸与纹理相同时,每个纹素对应一个绘制缓冲像素,可保持像素画和小图标清晰。元素应落在整像素上:优先锚定角落,而非可能落在半像素处的画布中心;也应避免居中轴心配奇数宽度等使边缘落在半像素上的尺寸。要将像素画放大两三倍而不模糊,将纹理 minFilter 和 magFilter 设为 pc.FILTER_NEAREST。

响应式布局​

屏幕空间界面跟随画布,画布尺寸则由屏幕之外控制:

开发方式画布尺寸由以下内容决定
引擎应用填充模式。pc.FILLMODE_FILL_WINDOW 填满窗口,pc.FILLMODE_KEEP_ASPECT 在保持比例的前提下尽量填充,pc.FILLMODE_NONE 交给 CSS。窗口变化时调用 app.resizeCanvas()
编辑器渲染设置中的 Fill Mode 与 Resolution Mode
React包含 <Application> 的元素,画布默认填满容器
Web Components页面 CSS,像调整 <video> 一样调整 <pc-app>,画布始终填满它

画布保持宽高比时,采用 Blend 的界面在各窗口中只会整体变大或缩小,布局不变。画布填满窗口或手机屏幕时,则需要自适应:

  • 将元素锚定到所属角落或边缘,使其随画布变宽、变高而跟随;需要拉伸的条和面板使用分离锚点。详见元素。
  • 将居中内容限制在支持的最小画布内,或按缩放混合值一节的方法,确保参考区域完整可见。
  • 手机上的关键元素应放在安全区域内。
  • 允许文本换行或缩小适配,详见文本元素。
  • 测试支持的最小和最大画布、横竖屏,以及 1、2 或更高的像素比。

多个屏幕​

应用可以包含多个屏幕,例如 HUD、暂停菜单和世界标牌,各自布局自己的元素。屏幕重叠时,priority 越高的越靠上显示,并优先检测输入,范围为 0 到 127。详见绘制顺序与性能。

显示与隐藏​

禁用屏幕实体可隐藏整个界面,重新启用即可显示。被禁用屏幕中的元素不接收输入。仅禁用 Screen 组件不会隐藏内容。

pauseMenu.enabled = true;

React 中,仅在需要显示时渲染屏幕的 <Entity>,因为 <Entity> 不应用 enabled prop。Web Components 中,将所属 <pc-entity> 的 enabled 属性设为 false。

另请参阅​