◆ 此篇客座文章由 ARKAI Studio 投稿,講述有關 Unity UGUI 的各種原理,幫助讀者們學習更多有關 Unity 技術上的知識,敬請大家多加參考利用!
Unity UGUI 原理篇 (一):Canvas 渲染模式
■ 了解各種不同 UI Render Mode
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
Canvas
Canvas Component 是UI布局和渲染的抽象空間,所有的UI都必須在此元素之下(子物件),簡單來說 Canvas 就是渲染 UI 的組件
Render Mode
UI渲染的方式,有以下三種
Screen Space – Overlay:螢幕空間 – 覆蓋
Screen Space – Camera:螢幕空間 – 攝影機
World Space:世界座標空間
Screen Space – Overlay
在此模式下不會參照到Camera,UI直接顯示在任何圖形之上
1.Pixel Perfect:可以使圖像更清晰,但是有額外的性能開銷,如果在有大量UI動畫時,動畫可能會不平順
2.Sort Order:深度值,該值越高顯示越前面
Screen Space – Camera
使用一個Camera作為參照,將UI平面放置在Camera前的一定距離,因為是參照Camera,如果螢幕大小、分辨率、Camera視錐改變時UI平面會自動調整大小。如果Scene中的物件(GameObject)比UI平面更靠近攝影機,就會遮擋到UI平面。
1.Render Camera:用於渲染的攝影機
2.Plane Distance:與Camera的距離
3.Sorting Layer:Canvas屬於的排序層,在 Edit->Project
Setting->Tags and Layers->Sorting Layers 進行新增,越下方的層顯示越前面
4.Order in Layer:Canvas屬於的排序層下的順序,該值越高顯示越前面
World Space
把物體當作世界座標中的平面(GameObject),也就是當作3D物件,顯示3D UI
1.Event Camera:處理UI事件(Click、Drag)的Camera,所設定的Camera才能觸發事件
參考資料
■ Unity – Manual: Canvas
http://docs.unity3d.com/Manual/class-Canvas.html
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
當 Pixels Per Unit=10,每單位由 10 Pixel組成,Sprite 是100*100 Pixels,那 Sprite 在世界座標中大小就會變成 100/10 * 100/10 = 10*10 Unit
結論:
上面官方程式碼,可以看出 Image 透過 spritePixelsPerUnit / referencePixelsPerUnit 方式算出新的 pixelsPerUnit
在設定 Image 圖片大小時,是把 寬高 / pixelsPerUnit
Canvas底下建立一個Image,Sprite設定為測試圖,參數如下
這邊做4種不同的測試:測試方式是修改 Reference Pixels Per Unit 與 Pixels Per Unit 後,點下 Image Compoent 的 Set Native Size來設定圖片原始大小,藉此看到圖片變化
結論:
新的 Reference Pixels Per Unit = Reference Pixels Per Unit * Physical Unit / Default Sprite DPI
UI大小 = 原圖大小(Pixels) / (Pixels Per Unit / 新的 Reference Pixels Per Unit)
■ Unity – Manual: Canvas
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Unity UGUI 原理篇(二):Canvas Scaler 縮放核心
2016-03-28 k79k06k02k
UGUI, Unity
■ 了解各種不同 UI Scale Mode
■ Pixels Per Unit 每單位像素
■ Canvas Scale Factor 縮放因子
■ Reference Resolution(預設螢幕大小)、Screen Size、Canvas Size 之間的關係與算法
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
Canvas Scaler
Canvas Scaler是Unity UI系統中,控制UI元素的總體大小和像素密度的Compoent,Canvas
Scaler的縮放比例影響著Canvas下的元素,包含字體大小和圖像邊界。
Size
Reference Resolution:預設螢幕大小
Screen Size:目前螢幕大小
Canvas Size:Canvas Rect Transform 寬高
Scale Factor
用於縮放整個Canvas,而且調整Canvas
Size與Screen Size一樣
先來看一段官方程式碼
CanvasScaler.cs C#
protected void SetScaleFactor(float scaleFactor)
{
if (scaleFactor ==
m_PrevScaleFactor)
return;
m_Canvas.scaleFactor = scaleFactor;
m_PrevScaleFactor
= scaleFactor;
}
程式碼可以看出,Canvas Scaler 透過設定Canvas下的Scale Factor,縮放所有在此Canvas下的元素
當Scale Factor為1時,Screen Size (800*600)、Canvas Size(800*600),圖片大小1倍
當Scale Factor為2時,Screen Size (800*600)、Canvas Size(400*300),圖片大小2倍
在當Scale Factor為2時,Scale Factor 會調整整個Canvas 的大小,並讓他的大小跟Screen
Size一樣,運算後Canvas Size放大2倍,剛好等於Screen Size,而底下的圖片會放大2倍
UI Scale Mode
Constant Pixel Size
Canvas Size 始終等於 Screen Size,透過Scale Factor直接縮放所有UI元素
1. Scale Factor:透過此Factor縮放所有在此Canvas下的元素
2. Reference Pixels Per Unit:
先介紹圖片檔設定中的Pixels Per Unit,意思是在這張Sprite中,世界座標中的一單位由幾個Pixel組成
這邊使用的測試圖片為原始大小100*100 的圖檔,這邊統稱測試圖
舉例來說,場景中有一個1*1 Cube ,與一個Sprite圖片指定為測試圖,兩者的Transform Scale 都為 1
當 Pixels Per Unit=100,每單位由 100 Pixel組成,Sprite 是100*100
Pixels,那 Sprite 在世界座標中大小就會變成 100/100 * 100/100 = 1*1 Unit
(左:Cube ,右:Sprite)
當 Pixels Per Unit=10,每單位由 10 Pixel組成,Sprite 是100*100 Pixels,那 Sprite 在世界座標中大小就會變成 100/10 * 100/10 = 10*10 Unit
(左:Cube ,右:Sprite)
結論:
■ Unity中一單位等於 100 Pixels
■ 由此可以推導出公式:
Sprite 在世界座標中大小 = 原圖大小(Pixels) / Pixels Per Unit
讓我們回到 Reference Pixels Per Unit,官方解釋是,如果圖片檔有設定Pixels Per
Unit,則會將Sprite 的 1 pixel 轉換成 UI 中的 1 pixel
Image.cs (C#)
public float pixelsPerUnit
{
get
{
float
spritePixelsPerUnit = 100;
if (sprite)
spritePixelsPerUnit = sprite.pixelsPerUnit;
float
referencePixelsPerUnit = 100;
if (canvas)
referencePixelsPerUnit = canvas.referencePixelsPerUnit;
return spritePixelsPerUnit /
referencePixelsPerUnit;
}
}
上面官方程式碼,可以看出 Image 透過 spritePixelsPerUnit / referencePixelsPerUnit 方式算出新的 pixelsPerUnit
Image.cs (C#)
public override void SetNativeSize()
{
if (overrideSprite
!= null)
{
float w =
overrideSprite.rect.width / pixelsPerUnit;
float h =
overrideSprite.rect.height / pixelsPerUnit;
rectTransform.anchorMax = rectTransform.anchorMin;
rectTransform.sizeDelta = new Vector2(w, h);
SetAllDirty();
}
}
在設定 Image 圖片大小時,是把 寬高 / pixelsPerUnit
實作一下,建立一個Canvas參數如下
Canvas底下建立一個Image,Sprite設定為測試圖,參數如下
這邊做4種不同的測試:測試方式是修改 Reference Pixels Per Unit 與 Pixels Per Unit 後,點下 Image Compoent 的 Set Native Size來設定圖片原始大小,藉此看到圖片變化
■ 上表可以看出當數值改變時,圖片預設大小也會改變
■ 由此可以推導出公式
UI大小 = 原圖大小(Pixels)
/ (Pixels Per Unit / Reference
Pixels Per Unit)
1. Reference Resolution:預設螢幕大小
2. Screen Match Mode:縮放模式
先來看官方的算法
CanvasScaler.cs C#
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(擴大):將Canvas Size進行寬或高擴大,讓他高於Reference Resolution,計算如下
scaleFactor = Mathf.Min(screenSize.x /
m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
意思是分別算出長寬 ,”Screen Size” 佔了 “Reference Resolution” 的比例,在求小的
舉例來說,Reference Resolution為1280*720,Screen Size為800*600
ScaleFactor Width: 800/1280=0.625
ScaleFactor Height:600/720=0.83333
套用ScaleFactor公式:Canvas Size = Screen Size / Scale Factor
Canvas Width:800 / 0.625 = 1280
Canvas Height:600 / 0.625 = 960
Canvas Size 為 1280*960,高度從720變成了960,最大程度的放大(顯示所有元素)
b. Shrink(收縮):將Canvas Size進行寬或高收縮,讓他低於Reference Resolution,計算如下
scaleFactor = Mathf.Max(screenSize.x /
m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
意思是分別算出長寬 ,”Screen Size” 佔了 “Reference Resolution” 的比例,在求大的
舉例來說,Reference Resolution為1280*720,Screen Size為800*600
ScaleFactor Width: 800/1280=0.625
ScaleFactor Height:600/720=0.83333
套用ScaleFactor公式:Canvas Size = Screen Size / Scale Factor
Canvas Width:800 / 0.83333 = 960
Canvas Height:600 / 0.83333 = 720
Canvas Size 為 960*720,寬度從1280變成了960,最大程度的縮小
c. Match Width or Height:根據Width或Height進行混合縮放,計算如下
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);
分別對ScaleFactor Width、Height取對數後,再進行平均混合,那為什麼不直接使用March對Width、Height進行混合呢??,讓我們來比較一下
假設Reference Resolution為400*300,Screen Size為200*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:2^0 = 1
scaleFactor一般混合為1.25,對數混合為1,結果很明顯,使用對數混合能更完美的修正大小
Constant Physical Size
2. Fallback Screen DPI:備用Dpi,當找不到設備Dpi時,使用此值
3. Default Sprite DPI:預設的圖片Dpi
C#
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 要與目前的Dpi在運算求出新的值,再傳入Canvas中求出大小,公式如下:
新的 Reference Pixels Per Unit = Reference Pixels Per Unit * Physical Unit / Default Sprite DPI
UI大小 = 原圖大小(Pixels) / (Pixels Per Unit / 新的 Reference Pixels Per Unit)
參考資料
■ Unity – Manual: Canvas
http://docs.unity3d.com/Manual/class-Canvas.html
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
目標:
☻ Window 7
Anchor位置座標與關係
點選 RectTransform 左上角,可以開啟Anchor Presets 工具,這邊列出了常用的 Anchor ,可以快速套用,按住Shift 可以連同 Pivot 一起改變,按住 Alt 可以連同位置一起改變
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Line. 2:using UnityEngine.EventSystems 匯入命名空間
點下 “+” 按鈕後,拖入要通知的Scene GameObject,Unity Event 就會尋找此 GameObject 上所有 Public 的方法與屬性 ,就可以新增 Event 觸發時 “通知的方法” 與 “預修改屬性”
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Unity UGUI 原理篇(三):RectTransform
目標:
■ 理解 RectTransform Component
■ Anchor (錨點)
■ Pivot (支點)
■ Blue Print Mode 與 Raw Edit Mode
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
RectTransform
RectTransform 是 Transform 的 2D 對應 Component,Transform 表示單個點,RectTransform
表示一個2D矩形(UI空間),如果父子物體都有RectTransform,那麼子物體可以指定在父物體矩形中的位置與大小,簡單來說RectTransform 就是定義UI元素的位置、旋轉、大小
Anchor (錨點)
物體的錨點(對齊點),如果父子都有 RectTransform 情況下,子物體可以依據 Anchor 對齊到父物體,又分為
Min 與 Max 位置,如下圖物體四周有4個三角形
Anchor位置座標與關係
當我們使用滑鼠點選4個三角形調整Anchor時,會貼心的出現比例訊息,此比例是子物體在父物體中的縮放比例
當Canvas 下有1張圖 Anchor Min 與 Anchor Max 皆為 (0.5 , 0.5),如下左圖部分
如果將Anchor Min調整為(0.3, 0.5) ,Anchor Max調整為 (0.5, 0.7),如下右圖部分
注意看 左圖 Pos X、Pos Y、Width、Height ,會改變為 右圖 Left、Top、Right、Buttom
因為當 Anchor 在同一點時,顯示的是物體的座標與大小,當 Anchor 不在同一點時(此時會形成矩形),顯示的會是
Anchor 矩形填充空間,如下圖,(P.S.在我們移動物體時會貼心的顯示目前與 Anchor 距離關係)
上面看完一定還是不了解怎麼運作,讓我們來透過實例了解一下
Canvas 下有5張圖,Anchor Min 與 Anchor Max 皆為 (0.5 , 0.5),物體的位置會對齊到父物體的中心,當父物體大小改變時,情形如下
Canvas 下有1張圖,Anchor Min 與 Anchor Max 皆為 (0.0, 1.0),物體的位置會對齊到父物體的左上角,當父物體大小改變時,情形如下,物體會固定在左上角
Canvas 下有1張圖,Anchor Min 為 (0.0, 0.0), Anchor Max 為 (1.0,
0.0),物體的位置會對齊到父物體的左下角與右下角,當父物體大小改變時,情形如下,物體寬度會隨著父物體改變
由上面的幾個實例可以知道,子物體會依據所設定 Anchor 對齊到父物體,當父物體大小改變時,透過 Anchor 更新子物體,上面有提到當我們點選4個三角形調整Anchor時,畫面會貼心的出現比例訊息,相信有經驗的人一定知道該比例的用意,此比例就是子物體在父物體中的縮放比例,以下舉例
原來數值
Parent Size (400, 350)
Image Size (120, 105)
Anchor Min 為 (0.2, 0.5), Anchor Max 為 (0.5, 0.8)
Parent Size 一半時數值
Parent Size (200, 175)
Image Size (60, 52.5)
Image Size Width =
400 * 50% * 30% = 60
Image Size Height = 350 * 50% * 30% = 52.5
Anchor Min 為 (0.2, 0.5), Anchor Max 為 (0.5, 0.8)
經由上面可以得知父物體在縮小2倍後,父物體透過子物體的 Anchor 比例更新子物體,透過這種方式,我們可以達到不同螢幕解析度自動改變UI大小與位置
Anchor Presets
點選 RectTransform 左上角,可以開啟Anchor Presets 工具,這邊列出了常用的 Anchor ,可以快速套用,按住Shift 可以連同 Pivot 一起改變,按住 Alt 可以連同位置一起改變
Pivot (支點)
物體自身的支點,影響物體的旋轉、縮放、位置,改變 UI Pivot 必須先開啟控制面板的 Pivot 按鈕,如下圖
當 Pivot (0.5, 0.5)
當 Pivot (0, 1)
Blue Print Mode(藍圖模式) 、 Raw Edit Mode(原始编辑模式)
Blue Print Mode (藍圖模式)
忽略了物體的 Local Rotation 和 Local Scale,方便以原來的旋轉與大小調整物體
忽略了物體的 Local Rotation 和 Local Scale,方便以原來的旋轉與大小調整物體
Raw Edit Mode (原始編輯模式)
在 Inspector 中調整 Pivot 和 Anchor 時,物體會維持目前的位置與大小(Inspector 中數值部分),調整情形如下,請注意數值部分
Inspector 中調整 Pivot
Inspector 中調整 Anchor
參考資料
■ Unity – Manual: Basic Layout
■ UnityのuGUIのレイアウト調整機能について解説してみる(RectTransform入門)
http://tsubakit1.hateblo.jp/entry/2014/12/19/033946
http://tsubakit1.hateblo.jp/entry/2014/12/19/033946
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Unity UGUI 原理篇(四):Event System Manager 事件與觸發
目標:
■ Event System 事件系統
■ Input Module 輸入控制
■ Graphic Raycaster
■ Physics Raycaster 與 Physics 2D Raycaster
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
Event System
在建立出UI時,Unity會自動幫我們建立Event System物件,此物件是基於滑鼠、觸摸、鍵盤的輸入方式,傳送
Event 到
Object 上,物件下有3個組件,分別為Event System Manager、Standalone Input Module、Touch Input Module
控管所有Event,負責將滑鼠、觸摸、鍵盤輸入方式(Input Module) 與
被選中的
Object 互相協調,每個
“Update” Event System 都會接收所有呼叫,並判斷出這一瞬間要使用哪種Input Modules
Event System Info
當按下Play後,點選Event System物件,會在inspector顯示
選中物件、位置、接收事件的Camera等等資訊
First Selected
執行時第一次要選擇的Object,例如:選擇為 InputField (輸入框)
後
,按下Play後就會將游標
Force 在
InputField 上
Send Navigation Events
是否開啟UI導航功能,導航功能是可以用鍵盤的 “上”、”下”、”左”、”右”、”Cancel(Esc)”、”Sumit(Enter)”
控制選擇的UI
Visualize Buttin: 按下Visualize可以看到物件指向的黃線
Drag Threshold
Drag Event靈敏度,越低越靈敏
電腦輸入控制模組,主要影響著滑鼠與鍵盤的輸入,使用 Scene 中的 Raycasters 計算哪個元素被點中,並傳遞
Event
Horizontal Axis
代表 Input Module 中的 Horizontal Axis,可以被設定為
Input Manager 中的值,Vertical Axis、Submit Button、Cancel Button 不多做贅述
Input Actions Per Second
每秒能輸入的最大按鈕與滑鼠次數
Repeat Delay
重複輸入的延遲
事件執行完整流程
鍵盤輸入
1.Move Event:透過 input manager 驗證輸入
axis、left、right、up、down
按鈕,傳遞給
selected object
2.Submit 、Cancel Button:物件已經 Preesed (按下)時,透過
input manager 驗證輸入 submit 、cancel
按鈕,傳遞給
selected object
滑鼠輸入
1.如果是新的按下
a.傳送 PointerEnter event
b.傳送 PointerPress event
c.將 drag 相關暫存
e.傳送 BeginDrag event
f.設定Event system中的 selected object 為按下的Object
2.如果是持續按下(Drag)
a.處理移動相關
b.傳送 Drag event
c.處理 Drag 時跨到其他物體的 PointerEnter event、PointerExit
event
3.如果是釋放(滑鼠放開)
a.傳送 PointerUp event
b.如果滑鼠放開與按下時的物件一樣,傳送 PointerClick event
c.如果有 drag 相關暫存,傳送 Drop event
d.傳送EndDrag event
4.滑鼠中鍵滾輪傳送scroll event
觸摸輸入模組,主要用於移動設備上,可以透過Touch、Drag的方式響應,使用 Scene 中的
Raycasters 計算哪個元素被點中,並傳遞 Event
事件執行完整流程
與Standalone Input Module 的滑鼠輸入一樣,滑鼠點下想成觸摸即可
4.Event System 觸發流程
1.使用者輸入(滑鼠、觸摸、鍵盤)
2.透過 Event System Manager 決定使用 Standalone 還是
Touch Input Module
3.決定使用的 Input Module 後,透過 Scene 中的
Raycasters 計算哪個元素被點中
4.傳送Event
建立 Canvas 物件時下的其中一個 Component,Raycaster
會觀察
Canvas下所有圖形,並檢測是否被擊中,射線檢測其實就是指定位置與方向後,投射一條隱形線並判斷是否有碰撞體在線上,射線檢測這點官方已經有詳細說明,這裡用於判斷是否點選到UI圖形
Ignore Reversed Graphics:
背對著畫面的圖形,射線檢測是否要忽略此圖形
舉例:當圖形Y軸進行旋轉180後,此時是背對著畫面,這時是如果有打勾,就會忽略不檢測此圖形
Blocked Objects 、 Blocking Mask:
主要用於當Canvas Component Render Mode 使用 World Space 或是
Camera Space 時,UI 前有 3D 或是 2D Object 時,將會阻礙射線傳遞到
UI 圖形
Blocked Objects 阻礙射線的 Object 類型
Blocking Mask 勾選的 Layer 將會阻礙射線
如果將Cube 的 Layer 改為 Test01 ,Blocked
Objects 設定為
Three D,Blocking
Mask 只勾選
Test01,再次點選重疊區域,會發現
Cube 會阻礙射線檢測,此時按鈕會接收不到射線,當然也不會有反應
Physics Raycaster (物理物件 射線檢測員)
Physics Raycaster (物理物件 射線檢測員)
組件位置:Unity Menu Item → Component → Event → Physics
Raycaster
透過 Camera 檢測 Scene 中的 3D GameObject(必須有
Collider Component),有實現 Event Interfaces 接口的物件將會接收到 Message 通知,例如能讓
3D GameObject 能接收 點下Event 或是 拖拉Event 等等…..,看更多Event 請點我
接下來讓我們透過實例理解
1.建立 EventSystem,進行 Event 處理
物件位置:Unity Menu Item → GameObject → UI → EventSystem
第一種 建立 Script 直接實作 Interfaces
a.建立一個 Script,實作 Event Interfaces
EventTest.cs (C#)
using UnityEngine;
using UnityEngine.EventSystems;
public class EventTest : MonoBehaviour, IPointerDownHandler
{
public void
OnPointerDown(PointerEventData eventData)
{
print(gameObject.name);
}
}
Line. 2:using
UnityEngine.EventSystems 匯入命名空間
b.建立一個3D物件(此稱為Cube),並增加
BoxCollider Component
c.將 Script 放至 Cube 下,Inspector 中會出現
Intercepted Events 資訊,顯示出正在監聽的 Event
d.此時點擊 Cube 就會通知 OnPointerDown 方法並傳入事件資訊
第二種 使用Event Trigger Component 實作
Interfaces
a.建立一個 Script,實作方法,用於接收 Event Trigger 通知
EventTriggerTest.cs (C#)
using UnityEngine;
using UnityEngine.EventSystems;
public class EventTriggerTest : MonoBehaviour
{
//BaseEventData 動態傳入事件資訊
public void
OnPointerDown(BaseEventData eventData)
{
print("OnPointerDown--BaseEventData");
}
//純呼叫
public void
OnPointerDown()
{
print("OnPointerDown--non");
}
//傳入int
public void
OnPointerDown(int i)
{
print("OnPointerDown--int");
}
}
Line. 2:using UnityEngine.EventSystems 匯入命名空間
Line. 6~8:實作方法,這邊實作3種
c.將 Script 放至 Cube 下
組件位置:Unity Menu Item → Component → Event → Event Trigger
f.此時會新增一個UnityEvents,是一種透過編輯器設定的方式,設定 Event 觸發時要通知的方法與屬性,詳細可以參考以下,這邊簡單說明
點下 “+” 按鈕後,拖入要通知的Scene GameObject,Unity Event 就會尋找此 GameObject 上所有 Public 的方法與屬性 ,就可以新增 Event 觸發時 “通知的方法” 與 “預修改屬性”
h.此時點擊 Cube 就會觸發 PointerDown ,通知
Script 中的3個方法
4.實作注意點:
■ 實作 Event Interfaces 的方式,一種是建立 Script 直接實作
Interfaces ,一種是使用 Event Trigger Component,由上面實作可以知道,使用 Event Trigger 的方式可以使用編輯器設定,設定觸發時的
“通知方法”
與
“修改屬性”,且更為彈性
Physics 2D Raycaster
組件位置:Unity Menu Item → Component → Event → Physics 2D
Raycaster
跟 Physics Raycaster 只差在於,Physics 2D Raycaster 是檢測
Scene 中的
2D GameObject,當然 GameObject 上必須有 Collider2D Component,這邊不再贅述
後記
我們透過輸入的方式不同與 Raycaster 的關係,理解了整個 Event System 觸發流程,而且也知道怎麼實作
Event 與應用
Event,不管是3D、2D、UI物件都可以方便的套用,大大提升開發速度、簡化語法,可說是非常方便的功能
參考資料
■ Unity – Manual: Event System
■ Unity – Manual: UnityEvents
■ Unity – Raycasting
■ 胡亂說‧隨便寫
– Unity:使用
UnityEngine.Events 讓程式更靈活、穩定
http://godstamps.blogspot.tw/2015/10/unity-unityengineevents.html
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Unity UGUI 原理篇(五):Auto Layout 自動佈局
2016-06-19 k79k06k02k UGUI, Unity
原文出處:http://wp.me/p7hYyg-8K
目標:
■ Auto Layout System 架構
■ Layout Element 元素大小
■ Horizontal、Vertical 、Grid Layout Group 元素排列
■ Content Size 與 Aspect Ratio Fitter 大小控制
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
Auto Layout System
Auto Layout System 是基於 Rect Transform Layout System 之上的系統,自動調整一個或多個的元素大小、位置、間格,又分為 Layout Controllers(父物件) 與 Layout Elements(子物件) 兩部分,一個簡單的 Auto Layout 架構如下 (此處介紹理論,實作留到後面)
Layout Element (子物件)
代表著每個元素的大小,擁有資訊如下:
點選UI後,可以在 Inspector 最下方切換為 Layout Properties 看到資訊
Layout Controllers 透過不同的佈局方式,取得 Layout Element size 分配子物件,基本原則如下
☻ 首先分配 Minimum Size
☻ 如果還有足夠空間,分配 Preferred Size
☻ 如果還有額外空間,分配 Flexible Size
從以下圖片可以看出圖片寬度的增長方式 (此處介紹理論,實作留到後面)
☻ 首先分配 Minimum Size (300,紅色部分)
☻ 如果還有足夠空間,分配 Preferred Size (300~500,綠色部分)
☻ 如果還有額外空間,分配 Flexible Size:1 (500~700,藍色部分)
比較特別的是 Flexible,他是代表著整個大小的比例,如果 Layout 下有2個物體,分別給 Flexible 設定為 0.3 與 0.7,那比例就會變成下圖 (3:7)
另外要注意的是,Text、Image Component 會根據內容大小自動分配 Preferred Size
Layout Controllers (父物件)
Layout Group
不會控制 Layout Controllers (父物件)自身大小,而是控制子物件大小與位置,在大多數情況下,根據每個元素的 minimum、preferred、flexible 大小分配適當的空間,layout group 之間也可以嵌套,又分為 Horizontal(水平)、Vertical(垂直)、Grid(格狀) 3種
Horizontal Layout Group
水平方向(Width) 排列子物件
組件位置:Unity Menu Item → Component → Layout → Horizontal Layout Group
Padding:填充內部空間
Spacing:每個元素間格
Child Alignment:當沒有填滿全部空間時,子物件對齊位置
Child Force Expand:強制控制子物件填滿空間
透過實例理解各參數:
A.開新 Scene
Unity Menu Item → File → New Scene
B.新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas
C.Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)
D.父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group
E.父物件下建立5個 Button(子物件),完成後如下,當大小改變時會自動分配子物件大小
F.此時在 Button 的 Rect Transform Component 就不能進行調整,因為我們已經透過 Horizontal Layout Group 進行分配空間,在 Rect Transform 會顯示目前被哪個 Layout Group 控制
G.將 Padding 數值調整如圖,可以看出填充區域
H.將 Spacing 數值調整如圖,可以看出元素區間
I.接下來我們將5個 Button 增加 Layout Element Component 覆蓋預設大小,用於手動設定每個元素的大小
組件位置:Unity Menu Item → Component → Layout → Layout Element
J.此時將 Horizontal Layout Group 的 Child Force Expand Width 取消勾選,不強制子物件填滿額外空間,而是透過 Layout Element 手動設定
K.這裡使用幾種不同的設定,來理解 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件
■ 複習一下子物件大小分配方式,如果不清楚請回去上面 Layout Elements 部分
☻ 首先分配 Minimum Size
☻ 如果還有足夠空間,分配 Preferred Size
☻ 如果還有額外空間,分配 Flexible Size
■ 將5個 Button 的 Layout Element Min Width 分別改為 20、30、40、50、60,此時可以看出每個 Button 寬度分佈,改變父物件大小時子物件大小並不會改變,因為只有分配 Min Width,並不會分配額外有效空間
此時改變 Horizontal Layout Group 的 Child Alignment,可以看出元素對齊
父物件 Layout Properties Min Width = 5個按鈕寬(20+30+40+50+60=200) + Spacing(40) + Padding Left、Right(20) = 260
■ 現在將第1個 Button 的 Layout Element 數值調整如圖
這邊設定 Preferred Width 為 100
1.首先分配 Minimum Size(20)
2.空間足夠的情況下,將會分配剩下的 Preferred Size (20~100 空間),如下所示
■ 現在將第1個 Button 的 Layout Element 數值調整如圖
這邊設定 Flexible Width 為 1
1.首先分配 Minimum Size(20)
2.如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
3.如果還有額外空間,分配剩下 Flexible Size,如下所示
■ 現在將 Horizontal Layout Group 的 Child Force Expand Width 勾選,讓子物件強制填滿
1.首先分配 Minimum Size(20)
2.如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
3.如果還有額外空間,分配剩下元素 Flexible Size 與 Child Force Expand Width
結論:
上面我們看到,所有元素會先被分配 Minimum Size,接下來還有足夠空間,將會分配剩下的 Preferred Size,最後才是 Flexible Size 與 Child Force Expand Width
至此我們了解到 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件
Vertical Layout Group
垂直方向(Height) 排列子物件,與 Horizontal Layout Group 只差在水平或是垂直,這邊不在贅述
組件位置:Unity Menu Item → Component → Layout → Vertical Layout Group
Grid Layout Group
網格方式排列子物件
組件位置:Unity Menu Item → Component → Layout → Grid Layout Group
Padding:填充內部空間
Cell Size:每個元素的寬高
Spacing:每個元素間格
Start Corner:開始排列的角落(位置),又分為 “左上”、”右上”、”左下”、”右下”,請仔細看元素數字
Start Axis:”水平” 或是 “垂直” 排列,請仔細看元素數字
Child Alignment:當沒有填滿全部空間時,子物件對齊位置
Constraint:排列限制
Flexible:自動根據大小彈性排列
Fixed Column Count:限制排列 “行數(直)”
Fixed Row Count:限制排列 “列數(橫)”
Layout Fitter
控制著 Layout Controllers 自身大小,大小取決於子物件,或是設定的大小比例,又分為 Content Size Fitter 與 Aspect Ratio Fitter
Content Size Fitter
控制著 Layout Controllers (父物件)自身大小,大小取決於子物件的 Minimum 或是 Preferred 大小,能透過 Pivot 改變縮放方向
組件位置:Unity Menu Item → Component → Layout → Content Size Fitter
Horizontal、Vertical Fit:水平、垂直 適應調整
None 不調整
Min Size 根據子物件的 Minimum 大小進行調整
Preferred Size 根據子物件的 Preferred 大小進行調整
透過實例理解:
如果我們現在有一個需求,必需要讓 “父物件大小” 根據 “子物件大小” 進行縮放,完成如下 (方便明顯看出父物件大小,增加黑色外框)
A.開新 Scene
Unity Menu Item → File → New Scene
B.新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas
C.Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)
D.父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group
這時如果增加 Button(子物件),上面有提到,Horizontal Layout Group 會根據子物件的 Layout Element 進行分配子物件大小,而不會修改父物件本身的大小,如下所示 (方便明顯看出父物件大小,增加黑色外框)
E.父物件下增加 Button(子物件),並增加 Layout Element Component 覆蓋預設大小,Minimum Width 調整為 100
組件位置:Unity Menu Item → Component → Layout → Layout Element
F.父物件增加 Content Size Fitter Component,Horizontal Fit 調整為 Min Size,透過子物件 Minimum Width 調整父物件本身大小 (Horizontal 方向其實就是取得子物件 Width)
G.此時如果 Button 複製增加,父物件本身的大小也會跟著改變,如下所示
H.調整父物件的 pivot,可以控制縮放方向,如下所示
I.通過上面實例,我們首先使用 Horizontal Layout Group 排列子物件,並在子物件增加 Layout Element 覆蓋預設大小,最後透過 Content Size Fitter 取得子物件 Layout Element 設定父物件大小,至此父物件大小就會根據子物件大小進行縮放
Aspect Ratio Fitter
控制著 Layout Controllers 自身大小,按照物件寬高比調整大小,能透過 pivot 改變縮放方向
組件位置:Unity Menu Item → Component → Layout → Aspect Ratio Fitter
Aspect Mode:調整模式
None:不調整
Width Controls Height:
基於 Width 為基準,依據比例改變 Height
當 Width 改變時,Height 會依比例改變
Height Controls Width:
基於 Height 為基準,依據比例改變 Width
當 Height 改變時,Width 會依比例改變
Fit In Parent:依據比例將 寬高、位置、anchors自動調整,使此圖形大小在父物件中完全貼齊,此模式可能不會包覆所有空間
調整比例 (方便明顯看出父物件增加黑底)
調整父物件大小,物體會依據比例貼齊父物件
Envelope Parent:依據比例將 寬高、位置、anchors自動調整,使此圖形大小完全包覆父物件,此模式可能會超出空間
調整比例 (方便明顯看出父物件增加黑框)
調整父物件大小,物體會依據比例包覆父物件
Aspect Ratio:比例,此數值為 寬/高
差別:
Content Size Fitter 是透過子物件自動進行調整大小
Aspect Ratio Fitter 是透過數值(寬高比)進行調整
後記
Auto Layout System 可以快速、方便的排列多個 UI,當大小改變時會自動調整內容,也能應用在多層崁套下,在日後調整與修改上也是非常方便與直覺,是 UI 系統中必學的功能之一 !!
參考資料
■ Unity – Manual- Auto Layout
http://docs.unity3d.com/Manual/UIAutoLayout.html
■ Unity – Manual- Auto Layout_UI Reference
http://docs.unity3d.com/Manual/comp-UIAutoLayout.html
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
Unity UGUI 原理篇(五):Auto Layout 自動佈局
2016-06-19 k79k06k02k UGUI, Unity
原文出處:http://wp.me/p7hYyg-8K
目標:
■ Auto Layout System 架構
■ Layout Element 元素大小
■ Horizontal、Vertical 、Grid Layout Group 元素排列
■ Content Size 與 Aspect Ratio Fitter 大小控制
使用環境 與 版本
☻ Window 7
☻ Unity 5.2.4
Auto Layout System
Auto Layout System 是基於 Rect Transform Layout System 之上的系統,自動調整一個或多個的元素大小、位置、間格,又分為 Layout Controllers(父物件) 與 Layout Elements(子物件) 兩部分,一個簡單的 Auto Layout 架構如下 (此處介紹理論,實作留到後面)
Layout Element (子物件)
代表著每個元素的大小,擁有資訊如下:
點選UI後,可以在 Inspector 最下方切換為 Layout Properties 看到資訊
Layout Controllers 透過不同的佈局方式,取得 Layout Element size 分配子物件,基本原則如下
☻ 首先分配 Minimum Size
☻ 如果還有足夠空間,分配 Preferred Size
☻ 如果還有額外空間,分配 Flexible Size
從以下圖片可以看出圖片寬度的增長方式 (此處介紹理論,實作留到後面)
☻ 如果還有足夠空間,分配 Preferred Size (300~500,綠色部分)
☻ 如果還有額外空間,分配 Flexible Size:1 (500~700,藍色部分)
比較特別的是 Flexible,他是代表著整個大小的比例,如果 Layout 下有2個物體,分別給 Flexible 設定為 0.3 與 0.7,那比例就會變成下圖 (3:7)
另外要注意的是,Text、Image Component 會根據內容大小自動分配 Preferred Size
Layout Controllers (父物件)
Layout Group
不會控制 Layout Controllers (父物件)自身大小,而是控制子物件大小與位置,在大多數情況下,根據每個元素的 minimum、preferred、flexible 大小分配適當的空間,layout group 之間也可以嵌套,又分為 Horizontal(水平)、Vertical(垂直)、Grid(格狀) 3種
Horizontal Layout Group
水平方向(Width) 排列子物件
組件位置:Unity Menu Item → Component → Layout → Horizontal Layout Group
Padding:填充內部空間
Spacing:每個元素間格
Child Alignment:當沒有填滿全部空間時,子物件對齊位置
Child Force Expand:強制控制子物件填滿空間
透過實例理解各參數:
A.開新 Scene
Unity Menu Item → File → New Scene
B.新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas
C.Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)
D.父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group
E.父物件下建立5個 Button(子物件),完成後如下,當大小改變時會自動分配子物件大小
F.此時在 Button 的 Rect Transform Component 就不能進行調整,因為我們已經透過 Horizontal Layout Group 進行分配空間,在 Rect Transform 會顯示目前被哪個 Layout Group 控制
G.將 Padding 數值調整如圖,可以看出填充區域
H.將 Spacing 數值調整如圖,可以看出元素區間
I.接下來我們將5個 Button 增加 Layout Element Component 覆蓋預設大小,用於手動設定每個元素的大小
組件位置:Unity Menu Item → Component → Layout → Layout Element
J.此時將 Horizontal Layout Group 的 Child Force Expand Width 取消勾選,不強制子物件填滿額外空間,而是透過 Layout Element 手動設定
K.這裡使用幾種不同的設定,來理解 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件
■ 複習一下子物件大小分配方式,如果不清楚請回去上面 Layout Elements 部分
☻ 首先分配 Minimum Size
☻ 如果還有足夠空間,分配 Preferred Size
☻ 如果還有額外空間,分配 Flexible Size
■ 將5個 Button 的 Layout Element Min Width 分別改為 20、30、40、50、60,此時可以看出每個 Button 寬度分佈,改變父物件大小時子物件大小並不會改變,因為只有分配 Min Width,並不會分配額外有效空間
此時改變 Horizontal Layout Group 的 Child Alignment,可以看出元素對齊
父物件 Layout Properties Min Width = 5個按鈕寬(20+30+40+50+60=200) + Spacing(40) + Padding Left、Right(20) = 260
■ 現在將第1個 Button 的 Layout Element 數值調整如圖
這邊設定 Preferred Width 為 100
1.首先分配 Minimum Size(20)
2.空間足夠的情況下,將會分配剩下的 Preferred Size (20~100 空間),如下所示
■ 現在將第1個 Button 的 Layout Element 數值調整如圖
這邊設定 Flexible Width 為 1
1.首先分配 Minimum Size(20)
2.如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
3.如果還有額外空間,分配剩下 Flexible Size,如下所示
■ 現在將 Horizontal Layout Group 的 Child Force Expand Width 勾選,讓子物件強制填滿
1.首先分配 Minimum Size(20)
2.如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
3.如果還有額外空間,分配剩下元素 Flexible Size 與 Child Force Expand Width
結論:
上面我們看到,所有元素會先被分配 Minimum Size,接下來還有足夠空間,將會分配剩下的 Preferred Size,最後才是 Flexible Size 與 Child Force Expand Width
至此我們了解到 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件
Vertical Layout Group
垂直方向(Height) 排列子物件,與 Horizontal Layout Group 只差在水平或是垂直,這邊不在贅述
組件位置:Unity Menu Item → Component → Layout → Vertical Layout Group
Grid Layout Group
網格方式排列子物件
組件位置:Unity Menu Item → Component → Layout → Grid Layout Group
Padding:填充內部空間
Cell Size:每個元素的寬高
Spacing:每個元素間格
Start Corner:開始排列的角落(位置),又分為 “左上”、”右上”、”左下”、”右下”,請仔細看元素數字
Start Axis:”水平” 或是 “垂直” 排列,請仔細看元素數字
Child Alignment:當沒有填滿全部空間時,子物件對齊位置
Constraint:排列限制
Flexible:自動根據大小彈性排列
Fixed Column Count:限制排列 “行數(直)”
Fixed Row Count:限制排列 “列數(橫)”
Layout Fitter
控制著 Layout Controllers 自身大小,大小取決於子物件,或是設定的大小比例,又分為 Content Size Fitter 與 Aspect Ratio Fitter
Content Size Fitter
控制著 Layout Controllers (父物件)自身大小,大小取決於子物件的 Minimum 或是 Preferred 大小,能透過 Pivot 改變縮放方向
組件位置:Unity Menu Item → Component → Layout → Content Size Fitter
Horizontal、Vertical Fit:水平、垂直 適應調整
None 不調整
Min Size 根據子物件的 Minimum 大小進行調整
Preferred Size 根據子物件的 Preferred 大小進行調整
透過實例理解:
如果我們現在有一個需求,必需要讓 “父物件大小” 根據 “子物件大小” 進行縮放,完成如下 (方便明顯看出父物件大小,增加黑色外框)
A.開新 Scene
Unity Menu Item → File → New Scene
B.新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas
C.Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)
D.父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group
這時如果增加 Button(子物件),上面有提到,Horizontal Layout Group 會根據子物件的 Layout Element 進行分配子物件大小,而不會修改父物件本身的大小,如下所示 (方便明顯看出父物件大小,增加黑色外框)
E.父物件下增加 Button(子物件),並增加 Layout Element Component 覆蓋預設大小,Minimum Width 調整為 100
組件位置:Unity Menu Item → Component → Layout → Layout Element
F.父物件增加 Content Size Fitter Component,Horizontal Fit 調整為 Min Size,透過子物件 Minimum Width 調整父物件本身大小 (Horizontal 方向其實就是取得子物件 Width)
G.此時如果 Button 複製增加,父物件本身的大小也會跟著改變,如下所示
H.調整父物件的 pivot,可以控制縮放方向,如下所示
I.通過上面實例,我們首先使用 Horizontal Layout Group 排列子物件,並在子物件增加 Layout Element 覆蓋預設大小,最後透過 Content Size Fitter 取得子物件 Layout Element 設定父物件大小,至此父物件大小就會根據子物件大小進行縮放
Aspect Ratio Fitter
控制著 Layout Controllers 自身大小,按照物件寬高比調整大小,能透過 pivot 改變縮放方向
組件位置:Unity Menu Item → Component → Layout → Aspect Ratio Fitter
Aspect Mode:調整模式
None:不調整
Width Controls Height:
基於 Width 為基準,依據比例改變 Height
當 Width 改變時,Height 會依比例改變
Height Controls Width:
基於 Height 為基準,依據比例改變 Width
當 Height 改變時,Width 會依比例改變
Fit In Parent:依據比例將 寬高、位置、anchors自動調整,使此圖形大小在父物件中完全貼齊,此模式可能不會包覆所有空間
調整比例 (方便明顯看出父物件增加黑底)
調整父物件大小,物體會依據比例貼齊父物件
Envelope Parent:依據比例將 寬高、位置、anchors自動調整,使此圖形大小完全包覆父物件,此模式可能會超出空間
調整比例 (方便明顯看出父物件增加黑框)
調整父物件大小,物體會依據比例包覆父物件
Aspect Ratio:比例,此數值為 寬/高
差別:
Content Size Fitter 是透過子物件自動進行調整大小
Aspect Ratio Fitter 是透過數值(寬高比)進行調整
後記
Auto Layout System 可以快速、方便的排列多個 UI,當大小改變時會自動調整內容,也能應用在多層崁套下,在日後調整與修改上也是非常方便與直覺,是 UI 系統中必學的功能之一 !!
參考資料
■ Unity – Manual- Auto Layout
http://docs.unity3d.com/Manual/UIAutoLayout.html
■ Unity – Manual- Auto Layout_UI Reference
http://docs.unity3d.com/Manual/comp-UIAutoLayout.html