Unity中的屏幕适配及PixelPerfect

PixelPerfect

什么叫PixelPerfect?

假设 1unit = 1 pixel

a

像素只可以等倍数的放大,比如1倍,2倍,3倍…

假设相机的Size是5 则在Editor屏幕中,一列(Heigh方向)显示10个像素. Game屏(目标设备)的分辨率的高必须为10的整数被
n x 10 (10,20,30,40 这样)

此时只要把Editor中的像素 1:n的复制到 Game屏 即可, 此时就是 PixelPerfect (n是整数倍)

再假设,此时更改Game屏的分辨率到 30x13 ,

需要把Editor中的10个像素 基于某种算法 复制到 Game屏的13个像素中 此时就不是PixelPerfect.

换句话说就是

目标设备分辨率(Game屏幕) 必须是 开发分辨率 (Editor屏) 的整数倍才行.

注意: 目标分辨率不能小于开发分辨率,比如 开发分辨率是100px高,但是设备分辨率只有50px高. 此时如果期望把100px显示在50px的设备上 必然会缩放,缩放必然会丢像素,所以无法为PixelPerfect

就着上面说,因为设备分辨率是固定的,所以能调整的仅有开发分辨率,也就是相机的Size.

假设 设备分辨率为1440x900 , 高度为900px. (1unit=1pixel) 则由如下关系

设备分辨率开发分辨率相机Size相机Size
900px900px4501x
900px450px2252x
900px300px1503x
900px225px112.54x

容易混淆: 开发分辨率并不是图片的大小,比如一张背景图可以是1000px x 1000px的 只不过显示的区域是900px 450px (仅仅显示一部分). 反过来说 一个角色 可以是 30px x 50px. 同理 显示的区域仍旧是 900px 450px. 图片画多大和开发分辨率无关.

PixelPerfect 适合的适配方案

8985113e-7962-4d5c-840a-a032ab77a46f

比如横板卷轴,设计关卡高度为300px,上下留出50px冗余 也就是 美术做了一张 1000px x 400px的图片. 其中间300px是所有设备都会显示的,上下个50px是根据设备不同.
有的显示有的不显示 且不显示的话也不会影响整体的游戏体验.

此时在保证PixelPerfect的情况下 设备分辨率必须满足

倍率设备分辨率高度范围
1x300px~400px
2x600px~800px
3x900px~1200px

假设设备分辨率(高度) 是 1000px

开发中的相机Size 2 N = 设备分辨率.

N一定为整数,从上面表中可以知道N此时为3 (因为1000px 在900px~1200px之间)

从而求出

开发中的相机Size = 设备分辨率/(2*N) = 1000/6 = 166.666666

反过来也可以说

通过把相机Size设置为166.666666, 使得原图以扩大3被的情况下映射到了1000px分辨率的设备上了. 从而达到了PixelPerfect.

注意:

Size=166.66666, 也就是一个屏幕内可以显示的像素是333.3333px. 这也是为什么图片要制作为 300px有效像素,然后上下再留出50px冗余像素的原因

不适合做PixelPerfect的例子

比如 设备分辨率是 850px

按照上面的公式 开发中的相机Size * 2 * N = 设备分辨率.

N的取值开发中相机Size*2
1x850px
2x425px
3x283.333px

可以看出

N=2 则 会显示出开发分辨率下425px的内容,但是美术画的图是1000px x 400px的,多出来25px空白,
N=1 则 显示283.333px的内容 小于300px的有效内容. 会显示不全. 比如上图例子中那样 可能头上的陷阱就看不到了.

此时 并没有办法使得在PixelPerfect的情况下使得开发分辨率锁定在300px~400px之间. 2x的情况会导致穿帮,3x会导致显示内容过小

如若要做PixelPerfect 则需要做不锁高的游戏,也就是游戏世界中的高度大于1个视口高度,比如泰拉瑞亚这种,世界很大,能看到的只是其中一个区域. 此时相机高度发生一定变化 并不会导致穿帮.
或者上下直接留黑边,然后采取N=2的情况去做处理.

普通的屏幕适配方案

对于普通游戏(非像素游戏),其实没有必要非达到PixelPerfect的. 那此时一般采取的适配方案是锁高,或者锁宽.或者两种之间的变种.

锁高

锁高也是最简单的一种. 比如开发分辨率设定是 任意宽度 x 1000px . 然后在给定 任意设备分辨率的情况下. 希望可以把这1000px都显示出来.无论能显示多宽的内容.

比如设备高度是 500px , 那就是把现有内容缩小一倍显示在屏幕上. 如果设备是800px 则是缩小0.8 (800/1000)显示在屏幕上.

注意: 容易和PixelPerfect混淆的是. PixelPerfect是通过调整CameraSize从而保证缩放比例一定是整数,而普通锁高适配是恒定CameraSize

啰嗦一句. 上面的公式 开发中的相机Size 2 N = 设备分辨率 同样也适用这里. 只不过开发相机Size恒定 . 而N就是真正缩放的倍数.比如上面例子中0.5(500/1000), 0.8(800/1000)

只不过这个N 在Unity的面板里面是看不到的.

比如开发分辨率定位720px x 1280px . 在Unity中讲CameraSize设置为6.4 (6.4x2=12.8 默认 1unit=100px)

97f07975-dba4-478c-ae39-f8e3d020e700

开发分辨率 720x1280 :

BaiduNetdisk_mac_2.2.2

设备分辨率 300x500:

c2cd50a9-8bc8-4023-90de-891ca8df826a

设备分辨率 30x300:

92b988e9-a161-41dd-8979-9d07efa78223

在锁高的情况下,上下两个五角星一直会显示,无论设备分辨率是多少.

此时并不用做任何的操作

锁宽

锁宽稍微要复杂一些. 首先要明确的是.适配的方式就是在保证宽高比的情况下 放大缩小.使得锁定的一方完全显示在屏幕内.

还是上面的例子. 开发分辨率是 720x1280 . 设备分辨率是 30x300 锁高的情况下就是把 1280px 缩放到 300px的设备上

缩放倍数 = 300/1280 = 0.234375
因为宽高比不便. 所以宽度被缩放到了0.234375 * 720px = 168.75px. 设备只有30px的宽. 所以只能看到上下两颗星星. 左右的看不到.

b1f0bbc9-5a2c-4d4f-9165-63e189e41659

f75f68ad-bd44-4776-b542-ac43712b090e

锁宽的情况下需要更改CameraSize从而使得在不同设备的情况下,在设备上看到的宽度和开发中的一样.

根据缩放宽高比不变这条可以推导公式
设定:
开发分辨率宽 = 开W
开发分辨率高 = 开H
设备分辨率宽 = 设W
设备分辨率高 = 设H

其中 开H 也就是最后需要求得的值.从而推导,再给定的设备上 需要把CameraSize调整到何值

推导得到

CameraSize = 开W 设H / (设W 2)

实际应用场景

实际项目中, UI层一般都采取的是Canvas的全屏适配.也就不存在锁宽锁高. 主要是Scene场景. 能想到的比较典型的例子是

涂鸦跳跃 (锁宽)

5fd1a19e-d57e-4be1-9057-c879817a638b

Flappy bird (锁高)

673be8de-23af-49f4-951e-d1684c59d226

坚持原创技术分享,您的支持将鼓励我继续创作!