在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選項,那就要設定Minimum和Maximum 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。這個限制以後會去掉。