查看: 1894|回复: 0
打印 上一主题 下一主题

[经验分享] Unity UGUI 原理篇

[复制链接]
may    

8830

主题

81

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52336
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

跳转到指定楼层
楼主
发表于 2018-7-22 01:39:58 |只看该作者 |倒序浏览

目标:
1、Canvas :了解 Render Mode的三种渲染模式
2、Canvas Scaler :解各種不同 UI Scale Mode
Pixels Per Unit 每單位像素
Canvas Scale Factor 縮放因子
Reference Resolution(預設螢幕大小)、Screen Size、Canvas Size 之間的關係與算法
环境:
Windows 10
Unity 2018.1.3

Canvas
通常称为画布。是UGUI的布局和渲染空间。

Render Mode的三种模式
Screen Space – Overlay:屏幕空間 – 覆盖
Screen Space – Camera:屏幕空間 – 摄像机
World Space:世界坐标空間

Screen Space – Overlay:

这个模式下面不参战任何摄像机。显示在任何物体上面
Pixel Perfect :增加抗锯齿。让UI更清晰的显示。但是有效率[color=rgb(85, 85, 85) !important]问题。特别是在有大量UI动画的时候。性能消耗严重。谨慎开启
Sort Order :排序的深度值。值越大。显示越靠前

Screen Space – Camera:

用一个摄像机物体做为参照,用于渲染和定位Canvas。因为是参照Camera的。Canvas的大小会根据摄像机的视锥大小、屏幕大小、分辨率自动调节,在Canvas和Camera直接的GameObject的会显示在UI前面
Render Camera : 参照的摄像机
Plane Distance : 与摄像机的距离
Sorting Layer : 排序层级,在Edit->Project Setting->Tags and Layers->Sorting 里面设置。越靠后的层级,显示越靠前
Order in Layer : 在同一显示层级上的显示排序。数值越大。显示越靠前
World Space:

这个模式是以世界坐标系显示UI。把UI当做一个3D物体来显示
Event Camera : 处理UI输入事件的摄像机。
一般来讲。用Screen Space – Camera模式比较普遍。UI和3D物体用两个摄像机来渲染。
Canvas Scaler

用来控制Canvas总体的缩放,Canvas Scaler的缩放因子是影响Canvas下面子UI的大小。只有Canvas在Screen Space的模型下。Canvas Scaler才起作用。在World Space模式下。和3D物体一样。
先来说说各个Size的关系
Reference Resolution : 預設螢幕大小
Screen Size:当前屏幕大小

Canvas Size:Canvas的大小

Scale Factor
这个值是用来缩放Canvas Size到Screen Size一样大

比如Scale Factor为1时。Screen Size为(1280*800)Canvas Size为(1280*800)
Scale Factor为2时。Screen Size为(1280*800)Canvas Size为(640*400)

UI Scale Mode
Constant Pixel Size:Canvas Size始终和Screen Size的大小一致。通过Scale Factor来缩放UI

Scale Factor:缩放因子。通过这个参数来缩放UI
Reference Pixels Per Unit:
先来说说图片导入里面的Pixels Per Unit。意思是这个Sprite在世界里。一个单位由多少个像素组织

用一个100*100的图来做测试
在场景中创建一个1*1大小的Cube。与一个Sprite在场景中做测试。两者的Transform Scale都为1.
当Pixels Per Unit为100时。图片在场景中的大小为100/100 * 100/100 = 1*1Unit;

当Pixels Per Unit为10时。图片在场景中的大小为100/10 * 100/10 = 10*10Unit;

由此可以推断:
Unity里面一个单位为100Pixel
由这个公式可以推导出一个Sprite在世界中的大小为(原尺寸)/Pixels Per Unit

然后回头再看看Reference Pixels Per Unit。通过网上看到的官方代码

可以看到Image的pixelsPerUnit是等于spritePixelsPerUnit/referencePixesPerUnit

通过实践测试。UI大小= 原Pixels /(PixelsPerUnit/referencePixesPerUnit)

Scale With Screen Size:透过设定的Reference Resolution(预设的屏幕大小)來缩放
Reference Resolution:预设的屏幕大小
Screen Match Mode:缩放模式
先来看一段官方的代码:
Vector2 screenSize = new Vector2(Screen.width, Screen.height);

float scaleFactor = 0;
switch (m_ScreenMatchMode)
{
case ScreenMatchMode.MatchWidthOrHeight:
{
// We take the log of the relative width and height before taking the average.
// Then we transform it back in the original space.
// the reason to transform in and out of logarithmic space is to have better behavior.
// If one axis has twice resolution and the other has half, it should even out if widthOrHeight value is at 0.5.
// In normal space the average would be (0.5 + 2) / 2 = 1.25
// In logarithmic space the average is (-1 + 1) / 2 = 0
float logWidth = Mathf.Log(screenSize.x / m_ReferenceResolution.x, kLogBase);
float logHeight = Mathf.Log(screenSize.y / m_ReferenceResolution.y, kLogBase);
float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, m_MatchWidthOrHeight);
scaleFactor = Mathf.Pow(kLogBase, logWeightedAverage);
break;
}
case ScreenMatchMode.Expand:
{
scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
break;
}
case ScreenMatchMode.Shrink:
{
scaleFactor = Mathf.Max(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
break;
}
}

a、Expand:扩大方式。
scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
scaleFactor 是取屏幕大小的宽高和预设的宽高比。取小的那个值
比如ReferenceResolution为(1280*720),Screen Size(800*480)
800 / 1280 = 0.625
480/720 = 0.67
套用ScaleFactor公式:Canvas Size = Screen Size / Scale Factor
Canvas Width:800 / 0.625 = 1280
Canvas Height:480/ 0.625 = 768
Canvas Size(1280*768)

b.Shrink:收缩。
scaleFactor = Mathf.Max(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);

如上面的数据
800 / 1280 = 0.625
480/720 = 0.67
套用ScaleFactor公式:Canvas Size = Screen Size / Scale Factor
Canvas Width:800 / 0.67= 1194
Canvas Height:480/ 0.67= 720
Canvas Size(1194*720)

c.MatchWidthOrHeight:根据宽高的比例来设置scaleFactor

float logWidth = Mathf.Log(screenSize.x / m_ReferenceResolution.x, kLogBase);
float logHeight = Mathf.Log(screenSize.y / m_ReferenceResolution.y, kLogBase);
float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, m_MatchWidthOrHeight);
scaleFactor = Mathf.Pow(kLogBase, logWeightedAverage);
公式里的m_MatchWidthOrHeight是外面可以设置的Match值。表示宽高对scaleFactor 的影响比重

Constant Physical Size:通过硬件的DPI来缩放Canvas Size

Fallback Screen DPI:备用DPI。在找不到设备的时候。用这个值
Default Sprite DPI:预设图片的DPI。

float currentDpi = Screen.dpi;
float dpi = (currentDpi == 0 ? m_FallbackScreenDPI : currentDpi);
float targetDPI = 1;
switch (m_PhysicalUnit)
{
case Unit.Centimeters: targetDPI = 2.54f; break;
case Unit.Millimeters: targetDPI = 25.4f; break;
case Unit.Inches: targetDPI = 1; break;
case Unit.Points: targetDPI = 72; break;
case Unit.Picas: targetDPI = 6; break;
}

SetScaleFactor(dpi / targetDPI);
SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit * targetDPI / m_DefaultSpriteDPI);

由代码可知:ScaleFactor为当前设备的DPI/目标单位的比例
ReferencePixelsPerUnit = 原始ReferencePixelsPerUnit * 目标单位的比例/预设的DPI

在实际项目中。一般用MatchWidthOrHeight模式。

Rect Transform
Rect Transform 是用来表示UI的位置、大小、缩放和旋转的组件










Anchors(锚点)
物体的对齐点。如果父物体有Rect Transform 。则以父物体的Rect Transform 为基准对齐
Anchors Min:左下角的对齐点。(0,0)为父物体的左下角,(1,1)为父物体的右上角
Anchors Max:右上角的对齐点

a、当Anchors的Anchors Min和Anchors Max为一个点时。如图



上面分别表示距离锚点坐标和UI的大小。
b、当Anchors的Anchors Min和Anchors Max形成一个矩形时。如图



而上图里面的Left/Top/Right/Bottom分别对应的是距离各种锚点的距离
在UI里面。锚点对应的都是在父物体里的相对位置。在改变父物体的大小和位置的时候。也会根据不同的对其方式来改变子物体的大小和位置
Pivot:物体的中心点。物体的缩放、旋转的中心都在在这个点上

Event System
Event System :这个组件是接受系统的输入。传递Event到Object上


EventSystemInfo:显示被选中的物体的名称、位置等信息

First Selected : 运行时。第一次选中的Object。用于默认选中
Send Navigation Events :是否开放UI的导航功能。导航功能可以用键盘上的“上”“下”“左”“右”“Cancel(Esc)”“Sumit(Enter)”来控制UI

把Navigation设置为Explicit模式
Select On Up :按下“上”键后会选中的物体。其他的不赘述
Visualize 按钮能看到跳转的模式

Drag Threshold
Drag Event的灵敏度,值越低越灵敏

Standalone Input Module:pc端的输入控制组件

Horizontal Axis: 代表在Input Modul中的Horizontal Axis。可以在Input Manager里面设置。其他的同理
Input Actions Per Second:每秒能输入最大鼠标的输入
Repeat Delay:重复事件的延迟

Event System的触发流程:
1、使用者输入(鼠标、触摸、键盘)
2、通过Event System Manager决定使用Standalone还是TouchInputModule
3、决定使用的InputModule后。通过Scene中的Raycasters计算哪个元素被点中
4、传递Event
在计算屏幕坐标转换成UI内的坐标时。Unity提供了一个接口:
RectTransformUtility.ScreenPointToWorldPointInRectangle。这个接口用来获取屏幕坐标转换成世界坐标之后。在矩形内的坐标
Graphic Raycaster

在Canvas下面有一个Graphic Raycaster组件。用来检测Canvas下的物体释放被点中
Ignore Reversed Graphics:是否忽略背着画的图形。
举个例子。当图形沿着Y轴旋转180度时,这个图形是不显示的。因为是单面图形。从背后不渲染。这个时候打勾的话。就忽略这个图形的碰撞检测
Blocking Objects:阻挡射线的Object类型
Blocking Mask:阻挡射线的Layer物体


来自:sheng2008

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏1 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-24 06:17 , Processed in 0.099662 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部