• 浅谈Unity UI适配(二)


    书接上回,继续讲CanvasScaler的第二种适配方式,ScaleWithScreenSize。

    2.2 Scale With Screen Size —— 屏幕尺寸比例

    这种缩放模式下的UI位置是根据屏幕的分辨率和设置的宽高比来调整UI的位置的,通常做屏幕UI自适应的时候都需要调整到这个缩放模式下。

    先来看官方的算法:

    1. Vector2 screenSize = new Vector2(Screen.width, Screen.height);
    2. float scaleFactor = 0;
    3. switch (m_ScreenMatchMode)
    4. {
    5. case ScreenMatchMode.MatchWidthOrHeight:
    6. {
    7. // We take the log of the relative width and height before taking the average.
    8. // Then we transform it back in the original space.
    9. // the reason to transform in and out of logarithmic space is to have better behavior.
    10. // If one axis has twice resolution and the other has half, it should even out if widthOrHeight value is at 0.5.
    11. // In normal space the average would be (0.5 + 2) / 2 = 1.25
    12. // In logarithmic space the average is (-1 + 1) / 2 = 0
    13. float logWidth = Mathf.Log(screenSize.x / m_ReferenceResolution.x, kLogBase);
    14. float logHeight = Mathf.Log(screenSize.y / m_ReferenceResolution.y, kLogBase);
    15. float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, m_MatchWidthOrHeight);
    16. scaleFactor = Mathf.Pow(kLogBase, logWeightedAverage);
    17. break;
    18. }
    19. case ScreenMatchMode.Expand:
    20. {
    21. scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
    22. break;
    23. }
    24. case ScreenMatchMode.Shrink:
    25. {
    26. scaleFactor = Mathf.Max(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
    27. break;
    28. }
    29. }

    下面,就详细的说一下Screen Match Mode缩放模式:

    Expand(扩大):将Canvas Size进行宽或高扩大

    scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);

     意思是分别算出长宽 ,也就是Screen Size在Reference Resolution的比例。

    举例来说,Reference Resolution为1280 X 720,Screen Size为800 X 600.

     套用ScaleFactor公式:

    实际结果同我们计算的一致:

     

    Shrink(收缩):将Canvas Size进行宽或高收缩

    根据官方代码,计算方式如下:

    scaleFactor = Mathf.Max(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);

    意思是分别算出长宽 ,也就是Screen Size在Reference Resolution的比例。

    举例来说,Reference Resolution为1280 X 720,Screen Size为800 X 600.

     套用ScaleFactor公式:

    1. Canvas Width: 800 / 0.8333 = 960
    2. Canvas Height:600 / 0.8333 = 720

    实际结果同我们计算的一致:

    Match Width or Height:根据Width或Height进行混合缩放

    根据官方代码,计算方式如下:

    1. float logWidth = Mathf.Log(screenSize.x / m_ReferenceResolution.x, kLogBase);
    2. float logHeight = Mathf.Log(screenSize.y / m_ReferenceResolution.y, kLogBase);
    3. float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, m_MatchWidthOrHeight);
    4. scaleFactor = Mathf.Pow(kLogBase, logWeightedAverage);

    分别对ScaleFactor Width、Height取对数后,再进行平均混合,那为什麽不直接使用March对Width、Height进行混合呢?? 让我们来比较一下:

    假设Reference Resolution为400 X 300,Screen Size为200 X 600 大小关系是

    Reference Resolution Width 是 Screen Size Width的2倍
    Reference Resolution Height 是 Screen Size 的0.5倍

    看起来会像下图:

     当March为0.5时,ScaleFactor应该要是 1 (拉平):

    ScaleFactor Width: 200/400=0.5
    ScaleFactor Height:600/300=2

    一般混合:

    ScaleFactor = March * ScaleFactor Width + March * ScaleFactorHeight
    ScaleFactor = 0.5 * 0.5 + 0.5 * 2 = 1.25

    对数混合:

    logWidth:log2(0.5) = -1
    logHeight:log2(2) = 1
    logWeightedAverage:0
    ScaleFactor:20 = 1

    scaleFactor一般混合为1.25,对数混合为1,结果很明显,使用对数混合能更完美的修正大小。

    2-3、Constant Physical Size —— 恒定尺寸

     

    属性说明:

    1、Physical Unit单位

     2、Fallback Screen DPI:备用Dpi,当找不到设备Dpi时,使用此值
    3、Default Sprite DPI:预设的图片Dpi

    官方代码:

    1. float currentDpi = Screen.dpi;
    2. float dpi = (currentDpi == 0 ? m_FallbackScreenDPI : currentDpi);
    3. float targetDPI = 1;
    4. switch (m_PhysicalUnit)
    5. {
    6. case Unit.Centimeters: targetDPI = 2.54f; break;
    7. case Unit.Millimeters: targetDPI = 25.4f; break;
    8. case Unit.Inches: targetDPI = 1; break;
    9. case Unit.Points: targetDPI = 72; break;
    10. case Unit.Picas: targetDPI = 6; break;
    11. }
    12. SetScaleFactor(dpi / targetDPI);
    13. SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit * targetDPI / m_DefaultSpriteDPI);

     

    结论

    ■ ScaleFactor 为 “目前硬件dpi” 占了 “目标单位” 的比例

    ■ ReferencePixelsPerUnit 要与目前的Dpi在运算求出新的值,再传入Canvas中求出大小,公式如下:

    新的 Reference Pixels Per Unit = Reference Pixels Per Unit * Physical Unit / Default Sprite DPI

    UI大小 = 原图大小(Pixels) / (Pixels Per Unit / 新的 Reference Pixels Per Unit)

    参考资料:
    【Unity3D-UGUI原理篇】(二)Canvas Scaler 缩放原理_Unity3D软件工程师。的技术博客_51CTO博客

    Unity UI Performance tips - Sharing my findings - Unity Forum 

    https://www.youtube.com/watch?v=be4gDI8RZ2U 

  • 相关阅读:
    【网络编程】UDP Socket编程
    YOLOv5_Android_USBCamera:支持USB摄像头的YOLOv5Android图像识别项目
    k8s中使用prometheus operator监控外部服务器部署的windows exporter
    Shiro入门基础知识&&案例实现&&与Web的集成
    地理地形sdk:Tatuk GIS Developer Kernel for .NET Crack
    练气第六天
    SpringBoot 集成 WebSocket
    Yolov8部署——vs2019生成解决方案问题
    一文读懂什么是布隆过滤器
    石油化工行业迎战涨价大潮,经销商分销系统平台数字化赋能经销商与门店
  • 原文地址:https://blog.csdn.net/qq_17758883/article/details/126514277