分享

UGUI源码学习之一(UI坐标系统)

 kiki的号 2017-06-04

本文章装载字:http://mp.weixin.qq.com/s?__biz=MzAxMDcxOTkxNQ==&idx=1&mid=402542189&sn=682dee9056d5059d5c17edd4e6865295

我们先从一个实际的需求出发。 
需求描述:3D游戏中的怪物死亡会随机掉落一个宝箱,当有宝箱掉落时需要实现一个 UI 宝箱效果,从怪物当时所在的屏幕坐标处飞到游戏的宝箱 UI 上,然后宝箱计数加1。 
解决思路

  1. 宝箱的动画属于 UI层 的东西,需要在 UI 坐标系上进行;

  2. 需要将怪物的 3D世界坐标 转换成 2D的UI坐标。

为了解决以上问题,我们先来了解一下UGUI中涉及到的坐标系,我把这些坐标系总结为三个类型:屏幕坐标系,UI逻辑坐标系和UI世界坐标系。下面来逐一介绍。

屏幕坐标系

屏幕坐标系是和屏幕分辨率一致的坐标系。 
屏幕坐标系以屏幕的左下角为远点,屏幕右上角的坐标是(Screen.width, Screen.height)。示意图如下图所示:

 
屏幕坐标系的范围和分辨率有关,例如 iPhone4S 就是 960*640, 5S 则是 1136*640等。不同型号设备的分辨率可能不同,因此屏幕坐标系的范围也可能不同。UI 界面显示的时候因为要照顾到不同分辨率的手机,所以不能以屏幕坐标系来进行布局。

UI逻辑坐标系

UI逻辑坐标系是我们在设计UI界面的时候的参考坐标系。 
参考坐标系一般对当前流行的手机的分辨率保持一致,例如当前流行的是 iPhone6s 的 2000*1125,则美术在制作界面示意图的时候就需要参考这个分辨率进行制作,保证在当前主流机型上有最佳的显示效果。 
uGUI中坐标系的起点和屏幕坐标系是相同的,界面的左下角是原点,size是通过 Canvas 和 Canvas Scalar 组件来确定的。如下图所示。


  1. 没有 Canvas Scalar 组件 
    此时 UI逻辑坐标系 == 屏幕坐标系一般不采用此种用法,除非只想针对一种分辨率设备来做UI或者有自己的屏幕适配方案。

  2. 有Canvas Scalar 
    顾名思义,Canvas Scalar 使用 RectTransform 的 localScale 来使得 UI逻辑坐标 * RectTranform.localScale == 屏幕坐标。 
    Canvas Scalar 有三种 UIScaleMode: 

    • Constant Pixel Size: 不论屏幕分辨率怎么变化,UI元素例如按钮在不同分辨率上占据的像素大小相同。这种情况下需要使用者来手动设置 ScaleFactor 来设置 localScale

 
例如屏幕大小变成了 960*640,则 Canvas 的大小便为 960*640。如果设置 ScaleFactor = 2, 则 localScale = new Vector3(2, 2, 2), Canvas 的大小为 480*320。此种设置的具体使用场景还未知。

  • Scale With Screen Size:根据实际屏幕的宽高来设置缩放 
    这种方式是根据屏幕的实际比例来调整 Size 和 Scale,调整Size保证和设计时一致,调整 Scale 是为了和屏幕坐标系一致。 
    这里需要填入一个 Reference Resolution,就是我们制作 UI 的时候的参考屏幕大小,这里为了示例,我设置成了 800*600,而屏幕分辨率是 960*640。 
    其中 ScreenMatchMode 又分为三种模式: 

    • Expand:尽量减小缩放 
      scale = Min(screenSize.x / ReferenceResolution.x, screenSize.y / ReferenceResolution.y)

    • Shrink:尽量放大缩放 
      scale = Max(screenSize.x / ReferenceResolution.x, screenSize.y / ReferenceResolution.y)

    • MatchWidthOrHeight:根据屏幕的宽或高或者之间的一个值来进行缩放 
      scaleWidth = screenSize.x / ReferenceResolution.x; 
      scaleHeight = screenSize.y / ReferenceResolution.y; 
      scale = scaleWidth * (1 - scaleWithWidthOrHeight) + scaleHeight * scaleWithWidthOrHeight 

      上面三种适配方式的结果如下:




一般在进行屏幕适配的时候会选择 MatchWidthOrHeight 来进行适配。

  • Scale with Physical Size:在像素上和设计时类似 
    scale = Screen.dpi / TargetDPI

在确定了 scale 之后,UI逻辑坐标系的大小 = 屏幕坐标系大小/scale,这样子可以保证UI逻辑坐标系的宽高比(Aspect Ratio)和屏幕坐标系的宽高比相同。

UI世界坐标系

UI世界坐标系是指通过 RectTransfrom.position 获取的坐标值。这个是由 Canvas 组件的 RenderMode 来决定的:

  • Screen Space - Overlay:则 UI 坐标系和屏幕坐标系完全一致,RectTransform.position 代表的就是屏幕坐标位置。

  • Screen Space - Camera:此时 Canvas 需要指定一个 Camera。根据Camera的 Projection,则又有不同。

    • Perspective: UI 坐标区域由 Camera 到 Canvas 的距离决定,不细述。

    • Orhographic: Camera.size 决定了 整个屏幕的 UI 坐标区域。

此时通过 Canvas 上的 RectTransfrom 的 localScale 来将 屏幕坐标规约到 UI 坐标区域。

此时如果需要获取需要获取一个UI的屏幕坐标,可以通过下述代码来获得:


  • World Space:此时没有 UI 坐标系这个概念了,不细述。

一些个人理解

  1. Overlay的 RenderMode 该如何选择?

    • 如果UI一致显示界面的最高层,那么使用 Screen-Space Overlay 模式即可;如果需要多个 Canvas 可以通过 Sort Order 来进行分成,Sort Order 越大显示越靠前;

    • 如果UI中间需要嵌入一个3D物体,例如背景UI在最底层,人物 avatar 显示在中间层,上层显示其他 UI界面,则使用 Screen-Space Camera,此时需要多个 Camera ,然后通过 Camera 的 depth 来控制显示的次序,depth 越大越后渲染,越靠前。另外各个 Camera 的 ClearFlags 需要正确设置,背景的设置为 Solid Color,负责擦屏幕;之后的设置为 Depth Only 即可;

    • 如果 UI 界面需要显示在世界中,则需要使用 World Space,例如在 VR 场景中。

  2. Canvas Scalar的 UIScaleMode 该怎么选择?怎么可以让UI可以适配所有设备? 
    这里介绍一下个人使用经验,因为其他用得不多,优点还不知道:

    • UIScaleMode 设置成 ScaleWithScreenSize;

    • Reference Resolution 设置成当前最主流机型的分辨率,同时告诉美术这个就是参照的大小;

    • Match 设置成0或者1,设置成0的时候就是按照宽度适配,则以后宽度不需要考虑适配,高度上进行适配,此时告诉UI在设计UI的时候高度上一定要设置成高度可以调节的;反之亦可。一般建议横屏设置成宽度不变,竖屏设置成高度不变。

  3. 什么时候用 UI 逻辑坐标系,什么时候用 UI世界坐标系? 
    在游戏制作过程中拼界面的时候用 UI 逻辑坐标系,这个时候需要使用 RectTransform 提供的 pivot, anchorPos等进行UI的对齐和大小设置; 
    在使用程序控制UI进行动画的时候最好使用 UI世界坐标系。

引题答案


代码工程放在github[https://github.com/tnqiang/UI_Flow_Effect]上,代码解释:

  1. 第一步需要将 source 3D 物体从世界坐标转换到屏幕坐标,这个需要3D世界摄像机才能取得;

  2. 第二步需要将这个屏幕坐标转换到 UI 世界的世界坐标中,这个需要看 Camara 的 RenderMode 是否是 Overlay,如果是则直接是世界坐标,否则需要UI的摄像机来帮助。

Refs:

  1. uGUI源代码之CanvasScaler[https:///Unity-Technologies/ui/src/0155c39e05ca5d7dcc97d9974256ef83bc122586/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs?at=5.2&fileviewer=file-view-default]


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多