unity3D遊戲開發十四之NGUI一

在Unity中,可以使用代碼控制其自身所攜帶的GUI來實現圖形界面的搭建。但是這些組件的搭建效率很低,而且已經無法滿足現在市場對圖形用戶界面美感的要求,所以,引入了NGUI來增加所要開發的圖形用戶界面的美感。NGUI是一個功能強大的UI系統,其事件處理通常由開發人員編寫C#腳本完成,並且是一個嚴格遵循KISS原則的Unity框架,該框架具有乾淨、簡約的代碼。

現在NGUI的各個版本很多,我這裏用的是3.0.6版本,導入NGUI包,成功後,會在菜單欄中顯示NGUI選項,如下圖:


依次打開菜單欄,NGUI->Open->UI Wizard選項,如下圖:


點擊Layer下拉列表,選擇Add Layer,創建一個叫NGUI的層,如下圖:


Camera選項中有3個選項,None,Simple2D,Advanced3D,Simple2D新建一個簡單的2D界面,沒有Z軸效果,Advanced3D新建一個3D界面,有Z軸效果,並且可以3D旋轉。我們點擊Create Your UI按鈕,創建一個UI界面,程序會自動爲我們創建一個有節點層級關係的一些物體,分別是UI根節點,,一個相機節點,一個錨點節點,和一個用於盛放按鈕等UI的Panel節點我們現在可以不用管這些節點的功能和作用,只要記住Panel節點即可,以後我們創建的所有按鈕等UI都放在Panel層級下,如下圖:


我們先來看看UIRoot,UIRoot總是放在NGUI UI層級的最上層。它用來使UI的縮放變得更容易。widget通常使用的是以像素爲單位的座標,但是一個800*400(dimensions的值)的widget會佔用800*400個單位(Unity中的單位),這相當大。UIRoot通過屏幕高度的反比來進行縮放,因此widgets都會很小,並且操作起來更容易。屬性如下圖:


其中,Scaling Style(縮放類型,包含三種),UIRoot有幾種縮放方式。最常見的就是PixelPerfect。這種方式下,你的UI一直都是以像素爲基礎,一個300*200的widget在屏幕上永遠佔用300*200像素。這就意味着,你的UI在低分辨率的機器上會顯得非常大,在高分辨率的機器上就會顯得很小。這個設置就是一直保持你的UI清晰。FixedSize是一個和它功能正好相反的設置。當UIRoot用了這個選項,你的屏幕永遠都會保持NGUI所關心的尺寸,不管你的實際屏幕是多大。就是說一個300*200的widget佔用了1920*1080的25%的屏幕,那麼當分辨率降低到1280*720的時候,它同樣佔用25%的屏幕。如果你不介意你的UI看起來像是不同的尺寸,也不關心是否清晰(就是可能一個小的UI被拉伸很大),那麼選擇這個選項。選擇它的時候,不要忘記設置Manual Height FixedSizeOnMobile是前兩種的組合。選擇這個選項後,會在pc或者mac等桌面設備上用“PixelPerfect”,在移動設備上用“FixedSize”。 如果你沒有選擇Fixed Size選項,那就要設置MinimumMaximum Height的值。這些值讓你的虛擬屏幕看起來在合理範圍。比如選擇了Pixel Perfect方式,Minimum Height設置爲720,那麼當有玩家把你的程序運行在800*600(高度是600,小於Minimun Height)的設備上時,你UI的行爲就和設置了“Fixed Size”模式、Manual Height值設爲720的時候一樣。

接下來我們看下UICamera,屬性如下圖:


UICamera真正做的事情是發送NGUI事件給所有被當前camera渲染的object,camera是UICamera腳本所在的那個。 其實這個腳本做的事情和UI無關。事實上如果你想讓遊戲裏面的object接收OnPress、OnClick、OnDrag等這類事件,你需要把UICamera掛在你的主相機上。遊戲場景裏面可以有多個UICamera。大多數遊戲一個掛在渲染widget的相機上,一個掛在渲染遊戲的相機上。

UICamera的選項Event Type用來決定腳本如何排序mouse或者touch觸發的事件。如果是UI模式,這些事件順序基於widget的depth——和渲染順序一樣。如果UICamera掛到了Main Camera上,那麼就需要把這個選項修改成World模式。這樣就會根據與相機的距離來排序點擊到的object。
Event Mask用來決定哪些層會接收事件。大多數情況下你需要的就是“Everything”,這個值會與UnityEngine.Camera's Culling Mask進行邏輯與運算,有需要的話你可以微調這個值。如果你修改了UI的game object的Layer記得調整Event Mask,否則你可能會發現UI不響應事件。
Debug選項用來顯示當前在鼠標下面的是什麼。如果你不知道是什麼東西接收了鼠標事件,勾選上這個選項你就可以在右上角看到了。 
Allow Multi-Touch選項用來控制是否支持多點觸碰。如果勾選掉,多點觸碰也會當做單點觸碰。
Sticky Tooltip選項用來微調tooltip的行爲。如果關掉,當鼠標再次移動的時候就會立即關掉tooltip。如果打開,只要鼠標一直在這個game object上,tooltip就會移至顯示。
Tooltip Delay用來控制當鼠標停在某個object上時,經過多長時間OnTooltip消息會被髮送到這個object上。以秒爲單位。 
Raycast Range控制raycast的長度,大多數情況下這個值可以被忽略。這個值是世界座標系的值,所以如果你的攝像機的near clip是0.3、far clipping是 1000,比較遠的物體可能不會響應click事件,比如可以把這個值設置爲2000(比far和near clipping大的值。)

Event Sources用來確定哪些事件類型會被處理。被勾選掉的事件就不會被處理。有些平臺會強制關閉一些事件。比如使用手柄時會自動關掉鼠標和touch時事件。

Thresholds可以調整click、drag和tap事件的閾值來微調鼠標和touch事件的行爲。以像素爲單位。

Axes和Keys部分用來控制哪個軸控制哪個方向的移動。這些名字需要和Input Manager裏面的一致。

UIAnchor,屬性如下圖:


UIAnchor讓你可以固定game objects在屏幕或者其他widgets的某一邊或者某一個角。這是一個關鍵的組件,用來在NGUI中創建模塊化的UI。

是否想讓你的一部分UI粘在屏幕的角落或者邊緣上?比如魔獸世界。在這個遊戲中,遊戲地圖永遠在屏幕的右上角,熱鍵一直在屏幕的下方,不管你用的是多大的屏幕分辨率。你如何做到類似的東西呢?用anchors。

NGUI的默認UI佈局會給你提供一個anchor——一個居中的anchor。以魔獸世界的UI爲例子,你需要增加額外的兩個anchor。一個設置成TopRight,另一個則爲Bottom。之後你給這兩個anchor增加一些子節點,然後修改屏幕的尺寸,你會發現UI會一直在你想要的地方(右上方或者下面)。
通過設置anchor的Container讓一個UI附着在另一個UI上。如果Container是UIWidget,那麼會用widget的dimesions來代替屏幕矩形(就是TopRight將將是相對與這個widget,而不是屏幕)。如果是game object,那麼這個矩形就是game object下的所有節點widget的bounds。因爲這個原因,當你用父節點當做Container的時候一定要注意,因爲父節點的Container大小會包含這個你要anchor的widget,這可能不是你要的效果(比如你要放在父節點的左上角,但是當這個widget到了左上角後,父節點的左上角由於這個widget的到來可能就變了,之後再次移動widget,周而復始……)。
調整Relative Offset來用相對值來改變位置。 如果X是1就是100%的container寬度. Y是1就是100%的container高度。 0.5 = 50%,等等。也可以是負數。
上面的調整也可以通過用Pixel Offset來實現。就和你想的差不多……通過給定的X、Y的值來以像素爲單位調整anchor的偏移。
默認情況下anchor只會執行一次。如果要在每個update裏面都執行,那勾選掉Run Only Once選項。

UIWidget,屬性如下圖:


 UIWidget是NGUI的基礎組件。簡單來說,就是一個你可以放在屏幕任意位置的矩形框。widget會有一定的面積(如下圖的白色框範圍),但是在運行的時候(Game View)是完全不可見的,所以非常適合當做其他組件的容器(讓所有的sprite或者label等以它進行各種對齊)。UIWidget也被用來當做所有NGUI元素的基類——所有你創建的sprites和labels。UILabel,UISprite,UITexture和UI2DSprite(Unity3D 4.3版本)都繼承自UIWidget。

UIPanel,屬性如下圖:


UIPanel用來收集和管理它下面所有widget的組件。通過widget的geometry創建實際的draw call。沒有panel所有東西都不能夠被渲染出來。如果你對Unity熟悉,你可以把UIPanel當做Renderer。

所有panel都有一個Depth值,會影響所有它包含的widget。如果你的UI有很多窗口,那麼最好每個窗口有一個panel。Panel上的depth權重會遠遠高於每一個widget的depth權重,所以保證panel不要使用同樣的depth。如果使用同樣的depth在panel上,那麼draw call會被自動拆分來保證渲染順序,所以會增加更多的draw call。

  • Alpha屬性影響所有在panel下面的widget。所以可以用它來淡出整個窗口。
  • 如果你的UI需要被燈光影響,需要勾選上Normals
  • 如果創建了一個有很多geometry的scrollable panel,你需要勾選Cull選項來減少三角形的數目。這樣也可能降低性能,因爲widget的可視性需要每次update都檢驗一次。
  • 勾選Static選項來告訴NGUI這個panel下面的widget不會被移動,這樣可以提高性能。NGUI會忽略所有的position/rotation/scale改變。所以在運行時移動widget不會有效——所以小心使用。
  • 如果要調試由panel創建的draw calls,Show All選項可能幫助到你。你會看到由panel創建的所有draw call,以渲染順序排序。每個draw call會包括它使用到material的詳細信息,那個widget用的這個material,甚至可以讓你關閉某些draw call來讓你查詢某些問題。
Panel會根據dimensions自動Clip所有它的子節點。使用這個功能需要選擇Clipping下拉列表中的任意選項,之後調整Scene View中紫色矩形的尺寸,就像調整widget的尺寸一樣。通過這樣做你可以把一個panel放到Scroll View中,讓他輕鬆的拖拽。
注意clipping的panel不能嵌套。每個panel只能clip自己管理的widget,如果一個panel在另外一個panel裏面,只有一個會影響到裏面的widget。這個限制以後會去掉。
發佈了98 篇原創文章 · 獲贊 15 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章