Unity中的单位长度与像素之间的关系

1.什么是像素?

像素是由很多个小方格组成,每一个小方格上都存储了位置信息和色彩信息。像素是图像的最小单位。

分享一个查阅资料中学习到的知识点:图像分为两类,位图和矢量图。

  • 位图(点阵图):由多个像素组成,当放大时被分为多个色块,而且放大的位图属于失真状态。平时拍照,扫描的图片等都属于位图。
  • 矢量图:通过数学公式计算获得的图像,无论怎样放大都不会失真,但是难以呈现色彩层次丰富的逼真图像。

2.图像分辨率与屏幕分辨率

  1. 图像分辨率:每英寸图片内有多少个像素点,单位为PPI(Pixels Per Inch),像素每英寸。例如72ppi代表每英寸包含72个像素点。
  2. 屏幕分辨率:屏幕每行的像素点数*屏幕每列的像素点数。例如1280*720代表横向1280像素纵向720像素,其总数为1280*720=921600个像素。

3.像素的作用

1.为什么图像(位图)放大后会变得模糊?

例如这是一张135*145的图,左边为正常情况下的全图,右边为放大之后的局部图。明显的看出放大之后图像失真了变得模糊了。那为什么图像会变得模糊呢?
这是因为图像放大后图像分辨率变小了,也就是每英寸显示的像素点数变少,所以变得模糊了。正常情况下单位面积内可以显示所有的像素点数比如10000个,而放大后单位面积内只能显示1000个像素点数。
所以可以推断出单位面积内的像素点越多,图像就会越清晰越逼真。


2.为什么分辨率越高的显示器越清晰?

例如两个显示器,A的分辨率是640*480,B的分辨率是1600*1200,那么A屏幕上能够显示的像素为640*480个,明显少于B屏幕能够显示的像素,这也就是为什么分辨率越高的屏幕越清晰。
假设有两个不同尺寸大小的屏幕A和B,A的尺寸比B大,但是他们的分辨率相同,那么他们同样清晰,不存在A比B清晰。

4.Unity中的单位与图片像素的关系


在Inspector面板的图像设置中有一个Pixels Per Unit参数。它代表Unity的一个单位长度包含本图片多少个像素。
在Unity中创建的Cube等基本图形默认就是一个Unity单位长度,一个单位长度在unity世界坐标中代表1米。
例如默认值为100,则代表一个Unity单位包含本图片100个像素。

例如还是这张小乌龟的图片,它是135像素*145像素。
那么它占了多少个Unity单位呢?
当Pixels Per Unit为100时则图片在高度上占了145/100=1.45个Unity单位高,左图所示。
当Pixels Per Unit为50时则图片在高度上占了145/50=2.9个Unity单位高,右图所示。
将图片放到场景中查看,验证所得的结论

 

5.Camera在正交模式下的Size与像素和Unity之间的关系

现在已经明白了Unity中单位与像素之间的关系,其实它与相机的视口也存在一定的关系。
结论是这样的:相机高度占的单位长度=相机的size * 2。

例如当前Camera的size为3,那么屏幕高度应该占了2*3=6个Unity单位,左图所示。
例如当前Camera的size为2,那么屏幕高度应该占了2*2=4个Unity单位,右图所示。
在场景中查看,验证结论。

 

既然屏幕高度的单位长度/2是相机的size大小,那么屏幕宽度占的单位长度与相机size大小有什么关系呢?

例如当前Camera的size为1,左图所示,可以看出是3个多单位长度。
例如当前Camera的size为0.5,右图所示,可以看出是1个多单位长度。
很明显屏幕宽度占的单位长度与相机size大小没有关系。


既然屏幕宽度占的单位长度与相机size大小没有关系,那么屏幕宽度与什么有关系呢?

新建一个cube,因为cube的长和宽都是1个单位长度。
调整Camera的size为0.5,则在屏幕高度上应该是0.5*2=1个单位长度,也就是正好可以放下1个cube。
例如屏幕的分辨率为5:4,如左图所示。
例如屏幕的分辨率为16:9,如右图所示。
不难发现,无论怎样调整分辨率,相机显示的单位高度都不会改变,但是仔细观察两种不同分辨率下的Game窗口,天空盒占的范围不一样。


所以得出结论:相机高度占的单位长度只由Camera的size决定,而相机宽度占的单位长度是由于分辨率不同再通过一个比例计算出来的。

是这样计算的。

又因为相机高度占的单位长度=相机的size*2,所以总结出来一个公式:


6.为什么场景视图的Scale不是1呢

还有一个问题就是为什么在Game视图中的Scale不为1。


改变不同的分辨率后测试后发现不同分辨率的Game视图不但Scale不为1而且还是不同的。

继续测试,当分辨率为2304*1440时(我的屏幕最大分辨率为这个),当Game窗口小时,Scale为0.256,当Game窗口大时,Scale为0.586。

结论:因为我们的屏幕太小了,无法显示这个分辨率的画面所以只能将相机画面等比例缩放,并不影响游戏。
比如我这台电脑的分辨率为2304*1440,而我游戏场景设置的分辨率为2560*1440,那么无论场景视图放到多大Scale都不可能为1。而如果游戏场景设置的分辨率比较小时在你的Game窗口就有可能会显示不缩放的Scale比例。

7.一个比较绕的关系

比如一张图片的分辨率为1024*219,然后游戏视图分辨率为1280*720。设置Pixels Per Unit为219,相机size为0.5,图片应该是正好为屏幕的高度。可是图片的宽度分辨率明明是219像素,为什么却在游戏视图中变成了720像素了呢。
因为相机的高度为1个单位长度,而图片也是一个单位长度,所以图片会输出整个画面的高度,所以才会显示720像素的高度。

 

8.对于2D游戏中的一些素材如何做到自适应

对于背景,按钮等都会用UGUI绘制,UGUI有可视化的自适应设置功能,但对于2D游戏中的精灵图片呢。

现在需要一张地面的图片始终与屏幕宽度一致,屏幕的分辨率为9:16,图片的分辨率为1024*219。放到场景中发现它并不能满足我们的要求。

第一种方法:调整相机的size
如果想让高度充满屏幕则size=图片的高度分辨率/Pixels Per Unit/2。
如果想让宽度充满屏幕则size=图片宽度占的单位长度/屏幕宽高比/2。

例如它的Pixels Per Unit为100。
则图片宽度占的单位长度=1024/100=10.24,屏幕宽高比=9/16=0.562,则size=10.24/0.562/2=9.1。
将相机的size调整为9.1,发现图片的宽度正好与屏幕的宽度吻合。


第二种方法:调整图片的Pixels Per Unit
例如相机的size为20。在不改变相机size的情况下,让图片与屏幕的宽度相符合。
屏幕长宽比=9/16=0.562,则size=20。则屏幕宽度的单位长度=0.562*20*2=22.48。
又因为图片的分辨率为1024*219。所以Pixels Per Unit=1024/22.48=44.91。
调整图片Pixels Per Unit为44.91,发现图片的宽度正好与屏幕的宽度吻合。


但是对于实际的项目来说需要做到动态自适应,而不是我们计算出来手动去修改数值。
1.首先可以改变图片的Pixels Per Unit,但是发现它是只读的属性。


2.根据不同分辨率改变相机的size的话场景中的其他元素都会受到影响。

由于以上两种方法都无法适用,所以对于2D精灵图片的自适应应该去改变图片的自身scale(这种方法会让图片拉伸变形,我还没有找到更好的解决办法)。

例如相机的size为15,屏幕的分辨率为9:16,图片的分辨率为1024*219,图片的Pixels Per Unit为100。
则屏幕长宽比=9/16=0.562,屏幕宽度占的单位长度=0.562*15*2=16.86。
我们可以这样理解。
当图片scaleX为当前scale时,图片宽度占的单位长度=1024/100=10.24。
当图片的scale为X时,屏幕宽度占单位长度=16.86。
可以列一个方程:图片scaleX/10.24=X/16.86。解出X=1.646。
将图片的scaleX设置为1.646,发现图片的宽度正好与屏幕的宽度吻合。

所以我们可以写一个自适应的脚本挂载到需要自适应的物体上

using UnityEngine;

public class Adjust : MonoBehaviour
{
    private SpriteRenderer spriteRenderer;//精灵渲染组件
    private float imageWidth;//图片的宽度

    private void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        imageWidth = spriteRenderer.bounds.size.x;//图片的宽度

        ReSize();
    }

    //重新定义Scale
    private void ReSize()
    {
        float scrreenWidth = Screen.width;//屏幕的宽度
        float screenHeigth = Screen.height;//屏幕的高度
        float cameraHeightUnit = Camera.main.GetComponent<Camera>().orthographicSize * 2;//屏幕高度占的单位长度
        float targetWidth = cameraHeightUnit * scrreenWidth / screenHeigth;//屏幕宽度占的单位长度

        //公式:当前物体的scale.x/当前图片宽度=目标的scale.x/屏幕宽度占多少个单位长度
        float targetScaleX = transform.localScale.x / imageWidth * targetWidth;//求出目标的scale.x
        Vector3 targetScale = transform.localScale;
        targetScale.x = targetScaleX;
        transform.localScale = targetScale;
    }
}



9.不同设备的分辨率自适应

先提两个概念
1.游戏有效内容:指游戏中一定要完整显示在屏幕上的内容。
2.游戏实际内容:指游戏的全部内容,其中包括有效内容和为了适配不同分辨率而增加的不重要的内容。

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/88242711