【Unity游戲開發】淺談 NGUI 中的 UIRoot、UIPanel、UICamera 組件


簡介

馬三最近換到了一家新的公司擼碼,新的公司 UI 部分采用的是 NGUI 插件,而之前的公司用的一直是 Unity 自帶的 UGUI,因此馬三利用業余時間學習了一下 NGUI 插件的使用,並把知識點記錄成博客與大家分享。

在我們使用 NGUI 插件創建的 UI 中,可以發現 UIRoot 物體和 Camera 物體上面都帶有 NGUI 特有的腳本組件,其中 UIRoot 物體上面帶有 UIRoot 和 UIPanel 兩個組件,而子物體 Camera 帶有一個 UICamera 組件,這三個都是 NGUI 體系中比較核心的組件,今天我們就來仔細研究一下他們。

淺談 UIRoot、UIPanel、UICamera 組件

UIRoot組件

UIRoot 組件總是出現在 NGUI 的 UI "樹"的最頂層,也就是那個“根”物體中。如下圖:

圖 1:UIRoot UIPanel 展示圖

它的作用是縮放 UI。美術人員制作的圖片一般都是以像素為單位,比如 1280 x 720 等等,而 Unity 中則是以米為單位,如果一個 100 x 100 的像素 UI 元件放入到一塊 1000 x 1000 分辨率的屏幕中,按理說這個 UI 元件應該是屏幕大小的 1%,但是因為 Unity 中的單位是米,所以它會從 100 x 100 像素的大小變為 100 x 100 米,這樣就會導致一個小 UI 變得非常非常大,而 UIRoot 這時就會通過屏幕來縮放 UI 控件,讓 UI 控件在視覺上是正常的。

在 UIRoot組件中,它提供了 3 中縮放的方式(即 UIRoot 組件下的 Type 值),分別為:PixelPerfect、FixedSize、FixedSizeOnMobiles。

PixelPerfect 指的是永遠保持像素大小不變,比如一張 100 x 100 像素的圖片,在 500 x 500 分辨率的屏幕上,它是 100 x100 像素,在 1000 x 1000 像素的屏幕上,它依舊是 100 x 100 像素,因為它的源文件就是這個大小,而 PixelPerfect 讓它一直保持這個大小。這樣就可以讓 UI 的圖片永遠保持最清晰,但是這個模式的缺點是會導致在高分辨率下 UI 顯得特別小,而低分辨率下 UI 又會顯得特別大。

FixedSize 模式和上面的模式正好完全相反。在 FixedSize 模式中,NGUI 將不再保護圖片的原始尺寸,只會關心 NGUI 自己所需的縮放參數,這種模式下必須設置 UIRoot 的 ManualHeight 值,然后 NGUI 會將所有的控件按照和這個值的比例進行縮放。比如:設置 ManualHeight 的值為 1000,然后一張 100 x 100 像素的圖片在高度為 1000 的屏幕分辨率下的占 1/10 的高度,那么當 UI 放到一個分辨率為 500 x500 的屏幕上時,它依然占 1/10 的高度,只不過圖片的尺寸被自動縮放為 50 x 50。這樣就保證了 UI 和屏幕的分辨率比例是一定的。

FixedSizeOnMobiles 是兩種方案的結合體,它會讓 UI 在 Pc、Mac、Linux 系統下自動采用 PixelPerfect,而在移動設備上自動采用 FixedSize。

如果沒有選擇 FixedSize,那么必須設置另外兩種縮放模式下的 MinimumHeight 和 MaximumHeight 兩個值。比如:選擇 PixelPerfect 模式,將 MinimumHeight 設置為 720,將 MaximumHeight 設置為 900,那么在一個分辨率為800 x 600 的屏幕上,因為屏幕分辨率的高度小於 UIRoot 中的最小高度, UIRoot 就會按照 FixedSize 模式下 ManualHeight 為 720 的情況進行處理。同理,如果將 UI 放到一個分辨率為 1920 x 1080 的屏幕上,因為該屏幕的分辨率高度 1080 大於設置的 900,於是 UIRoot 就會按照 FixedSize 模式下 ManualHeight 為 900 的情況進行處理。(在 NGUI3.7.0 以后縮放模式變為了 Flexible:等同於 PixelPerfect、Constrained:等同於 FixedSize、ConstarinedOnMobiles:等同於 FixedSizeOnMobiles)。

UIPanel組件

如下圖所示,UIPanel 也有很多的屬性。其中,Alpha 屬性顧名思義是透明度,默認為 1 不透明。它將控制它下面所有 Widget 的透明度。(所有的 UI 控件都帶有 Widget,因為它們都繼承自 Widget)也就是說,它會讓它的子物體里的所有的 UI 控件都一起發生透明度變化,可以用來做整個 UI 的淡入淡出以及隱藏等。

圖 2:UIPanel 展示圖

Depth 深度屬性是一個非常重要的屬性。在 NGUI 中,每一個 Panel 都有 Depth,每一個 Widget 控件也都有 Depth,Depth 將決定渲染的順序,直接影響了 UI 之間的的前后重疊關系。Depth 越高的控件將會顯示在視野的上層,Depth 越高的 Panel 也會顯示在視野的上層。但是 Panel 的 Depth 權重要遠遠高於 Widget,也就是說,在大部分的情況下,屬於低 Depth 的Panel 的控件,無論你怎么去提高控件的 Depth,它都將顯示在高 Depth 的 Panel 的控件后面。當你有多個 Panel 的時候,比如你制作了多個面板界面,每個界面都有一個 Panel ,那么此時盡量保證這些 Panel 不要共用同一個 Depth,因為這將會導致 NGUI 在渲染的時候無法以 1 個 DrawCall 完成,會以增加 DrawCall 的方式來保證渲染順序不混亂,這樣就增大了性能的開銷。不過 NGUI 在碰到 Panel 有共用的 Depth 時,會做出提醒。

Clipping 是剪輯窗口的意思,它可以讓一個面板只顯示某一塊區域,這個功能在 ScrollView 滾動框或者滾動列表中非常有用。Clipping 一共提供了 3 中模式:

  • None:無剪輯模式,在這種模式下,滾動視框中的物體可以被拖動,但是視窗因為沒有剪輯,所以是沒有邊界的。這將可能導致內容被拖出屏幕外再也拖不回來。就像我們往下拖動瀏覽網頁時會拖到一個所謂的“底”,None 模式就是沒有這個“底”,你可以將內容全部拖出屏幕以外。
  • SoftClip:柔和剪輯模式,我們一般都會使用這種模式來制作 ScrollView。在這種模式下,Panel 將會剪輯出一塊可視區域出來顯示,這個被剪輯出來的區域以外的部分將會被剪輯掉而無法顯示出來。
  • Constrain but don't Clip:這種模式是指視窗會盡量地包含所有的內容,但是不剪輯它們,效果大約等同於有邊界但是邊界為全屏,無法完全將內容拖到屏幕外面去,只要在屏幕范圍內,都能看到內容,內容並不會被剪輯掉。

Render Q 可以理解為渲染順序,默認為自動設置。這個選項在和粒子系統結合使用的時候會有影響(下文會單獨拿出一段來解釋它)。如果該 Panel 下的 UI 需要被燈光影響到(NGUI 的 UI 默認是不會接受燈光照射效果的),則需要勾選 Normals。如果該 Panel 下面所有的 UI 控件都不會被移動,那么可以勾選 Static 來將他們設置為靜態的,這樣該 Panel 下所有的控件將會忽略位置、旋轉、縮放等操作,永遠保持不動。雖然這樣可以提高一些性能,但是慎重使用。

這段我們來主要了解一下 Render Queue 和粒子系統的一些聯系。有的時候,我們會發現粒子不能正確的顯示在界面上面,很多情況就是 Render Queue 的鍋。在上面我們了解到了,在 NGUI 中,渲染的層級關系是由 Depth 決定的,但是最本質的還是由渲染的 Render Queue 決定的,這是一個 Shader 中常見的參數。在 NGUI 中,每一個 Panel 上也有一個 RenderQ 的設置項,RenderQ 越高的將會越在上層顯示。粒子系統的 RenderQ 一般是 3000,所以,如果我們希望粒子處於兩個 Panel 之間,只需要將其中一個 Panel 的 RenderQ 改為 StartAt 模式,將值設為 3000 以下的值,然后將另外一個 Panel 的 RenderQ 設為 3000 以上的值,就可以讓粒子在兩個 Panel 之間顯示了。當然,如果只需要讓粒子顯示在最上層,最簡單的辦法就是加入一個攝像機,給這個粒子設置一個單獨的 Layer ,讓新加入的攝像機只渲染粒子所在的 Layer,將這個攝像機的 Clear Flag 設為 Depth Only,然后把渲染的 Depth 值設為最高的即可。

點擊 Show Draw Calls 按鈕,可以看到該 Panel 下的所有的 DrawCall 消耗情況。

UICamera 組件

下圖即為 UICamera 組件的截圖,UICamera 這個組件的核心作用是:讓帶有這個組件的攝像機渲染出來的物體能夠接受 NGUI 事件。如果我們自己創建了一個物體,並且希望對這個物體使用一些 NGUI 中的事件,比如 OnPress()、OnDrag() 等,就需要為渲染這個物體的攝像機添加 UICamera 組件。

圖 3:UICamera 展示圖

在 UICamera 中,大部分的設置我們都不用去改變,它讓我們的事件支持多點觸摸、鼠標鍵盤觸摸屏等事件的接受。但是要注意的是 EventMask 這個選項,這個 EventMask 和相機中的 CullingMask 非常相似,相機的 CullingMask 是為了選擇渲染哪些層的物體,而 EventMask 是為了選擇接受哪些層的物體的事件。UICamera 會默認只接收我們創建 UI 時被自動設置的那個 Layer,但是,如果我們在制作 UI 過程中,在創建 UI 后因為某些原因修改了 UI 的層,一定要記得將 UICamera 的 EventMask 修改過來,否則將會發現,我們單擊 UI 沒有反應,因為它接收不到這個 Layer 的物體的事件。

 

作者:馬三小伙兒
出處:http://www.cnblogs.com/msxh/p/6574554.html 
請尊重別人的勞動成果,讓分享成為一種美德,歡迎轉載。另外,文章在表述和代碼方面如有不妥之處,歡迎批評指正。留下你的腳印,歡迎評論!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM