生活随笔
收集整理的這篇文章主要介紹了
FGUI的常用方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
素材管理
可以直接將圖片(Gif)、聲音(mp3)、動畫、文字等素材從資源瀏覽器拖動到庫中。
資源Url
UIPackage.getItemURL(“包名“,“資源名”) AudioClip clip = (AudioClip)UIPackage.GetItemAsset(“包名稱”,”聲音名稱”);菜單”編輯”->“創建位圖字體”,(輸入字符,顯示對應圖片) 多信息文本(GRichTextField)支持鏈接和圖文混排。 用例: aTextField.text = “請去找王大錘”;列表 (GList) AddChild : 增加一個項目。 AddChildAt :在指定的位置增加一個項目。 RemoveChild : 刪除一個項目。 RemoveChildAt : 刪除一個指定位置的項目。 RemoveChildren : 刪除一個范圍內的項目,或者全部刪除。 GList內建了對象池。 使用對象池后的方法: AddItemFromPool : 從池里取出(如果有)或者新建一個對象,添加到列表中 GetFromPool : 從池里取出(如果有)或者新建一個對象 ReturnToPool : 將對象返回池里 RemoveChildToPool : 刪除一個列表項目,并將對象返回池里 RemoveChildToPoolAt : 刪除一個指定位置的項目,并將對象返回池里 RemoveChildrenToPool:刪除一個范圍內的項目,或者全部刪除,并將刪除的對象都返回池里 添加對象時不使用池,對象池將不斷增大。 正確的做法:從池中創建對象。即使用AddItemFromPool或GetFromPool。虛擬列表 GList.SetVirtual 使用GList.numItems設定列表項目的數量。注意與GList.numChildren區分,后者是當前列表容器的顯示對象數量。 但要注意顯示對象和列表項目的數量在數量上和順序上都是不一致的,也就是GetChildAt(0)獲得的顯示對象并不等于列表的第一條項目。 列表滾動到目標位置(第500個),調用GList.AddSelection(500) 虛擬列表只能通過numItems改變列表項目的數量,不允許使用AddChild或RemoveChild增刪對象。例如如果要清空列表,必須要通過設置numItems=0,而不是RemoveChildren。 循環列表 GList.SetVirtualAndLoop()。GList.ensureBoundsCorrect()通知GList立刻重排。(手動觸發重新排列)裝載器 GLoader 運行時設置裝載器內容的方式是: aLoader.url = “ui://xxxxx”; aLoader.url = “demo/aimage”; //這里加載的是路徑為Assets/Resources/demo/aimage的一個貼圖 例如,你希望從AssetBundle中獲取資源,那么你可以擴展GLoader。首先編寫你的Loader類,例如:這是一個egret中使用到的自定義loader,使用getResByUrl這個API加載外部資源。 然后我們就可以用fairygui.UIObjectFactory.setLoaderExtension(MyGLoader);注冊我們要使用的Loader類。注冊完成后,游戲中所有裝載器都是由MyGLoader實例化產生。 組件 點擊穿透 默認情況下,組件的矩形區域將攔截點擊,勾選后,點擊事件可以穿透組件中沒有內容的空白區域。 控制器 Controller Controller c1 = aComponent.GetController(“c1”) c1.selectedIndex = 1;//1是頁面索引 或 c1.selectedPage = ‘pageName’;//pageName就是頁面名稱說明: 對所有參與的頁面,元件將分別保存不同的坐標值;對所有沒有參與的頁面,元件將保存同一個坐標值。 緩動功能 (位移的插值?) 按鈕控制器 Button 單選組(RadioGroup) 在程序中,要獲得或設置哪個按鈕被選中也非常簡單,使用控制器的selectedIndex或者selectedPage就可以了。設置關聯 ( 類似錨點,相對位置的設置 )這里有一個垂直中線的關聯,下面會說明,暫且不表。置可以看到,在文本內容發生變化時,文本的中線位置沒有發生變化,位所以問號圖標的置不變;但文本的右側位發生了變化,所以嘆號圖標隨之發生了移動,保持了與文本右側的距離。 在代碼中設置關聯 (比如瀏覽器窗口被玩家拖大拖小),組件依然保持在右側位置,那么可以這樣調用: aComoponet.addRelation(GRoot.inst, RelationType.Right_Right);又例如希望一個動態添加到舞臺的組件始終保持滿屏大小,可以這樣調用 aComoponet.setSize(GRoot.inst.width, GRoot.inst.height); aComoponet.addRelation(GRoot.inst, RelationType.Size);RelationType.Size相當于RelationType.Width_Width和RelationType.Height_Height的組合。這里強調一下,使組件變為滿屏大小這個操作必須由你完成,也就是上面代碼中的setSize調用。關聯并不能完整這項任務,因為關聯是不管元件當前的大小的,它只會在目標變化時保持兩者大小的差別。A:和容器組件”垂直中線“關聯 B:和容器組件”右->右”關聯 C:和容器組件“右->右”,”底->底“關聯 D:和容器組件”底->底”,“垂直中線%”關聯 E:和容器組件“底->底”關聯 然后運行時把這個界面設置為滿屏就可以了。 aComponent.SetSize(GRoot.inst.width, GRoot.inst.height); aComoponet.addRelation(GRoot.inst, RelationType.Size);//當屏幕改變時仍然保持全屏FairyGUI教程:(九)組件的擴展 FairyGUI提供的控件有: 圖片(GImage)、動畫(GMovieClip)、圖形(GGraph)、文本(GTextField)、多信息文本(GRichTextFIeld)、列表(GList)、裝載器(GLoader)、組件(GComponent)。這些都是非常基礎的控件,他們是UI制作中的最小粒度。但僅靠這些基礎控件是不足以制作出各種復雜的UI界面的。我們通過”擴展“功能,從組件(GComponent)中擴展出來以下這些復合組件:按鈕(GButton),標簽(GLabel),下拉框(GComboBox),進度條(GProgressBar),滑動條(GSlider),滾動條(GScrollbar)。可以看到有六種“擴展”選擇。組件可以隨意在這些“擴展”中切換。選擇哪種“擴展”,組件就有了哪個擴展的屬性和行為特性。 指定統一點擊音效 如果希望游戲中所有按鈕的點擊都有聲音反饋,你并不需要每個按鈕都設置一次聲音屬性,因為在游戲中可以使用代碼UIConfig.buttonSound=’xxx’為所有按鈕設置一個點擊聲音。 滾動條 運行時使用的滾動條需要通過以下代碼設置: UIConfig.horizontalScrollBar = ‘xxx’; UIConfig.verticalScrollBar = ‘yyy’; 這里xxx和yyy就是滾動條資源的url。 UIConfig.defaultScrollBarDisplay = ScrollBarDisplayType.Auto; // 設置為,滾動時顯示滾動條9、自定義擴展 當基礎組件、擴展組件都不能滿足你的需求時,你可以編寫自定義的擴展。使用API UIObjectFactory.setPackageItemExtension完成定義。例如: UIObjectFactory.setPackageItemExtension(UIPackage.getItemURL(“包名“,”組件A”), MyComponent ); public class MyComponent extends GComponent { override protected function constructFromXML(xml:XML):void { super.constructFromXML(xml); //在這里繼續你的初始化 } } 這樣就為組件A指定了一個實現類MyComponent 。以后所有組件A創建出來的對象(包括在編輯器里使用的組件A)都為MyComponent 類型。例如: var obj:MyComponent = UIPackage.createObject(“包名“, ”組件A”) as MyComponent ; 注意:如果組件A只是一個普通的組件,沒有定義“擴展”,那么基類是GComponent,如上例所示;如果組件A的擴展是按鈕,那么MyComponent的基類應該為GButton,如果擴展是進度條,那么基類應該為GProgressBar,等等。這個不要弄錯。控制器Tween效果 動效的播放在代碼中啟動,例如: someComponent.GetTransition(“peng”).Play(); Play有多種原型,例如可以重復播放一定次數,可以在播放結束時回調等。要中途停止動效的播放,可以調用: someComponent.GetTransition(“peng”).Stop(); Stop方法也可以帶參數,原型是 public void Stop(bool setToComplete, bool processCallback); setToComplete表示是否將組件的狀態設置到播放完成的狀態,如果否,組件的狀態就會停留在當前時間。processCallback是否調用Play設定的播放完成回調函數。注意:UI動效播放完畢后,組件的狀態將停留在最后一幀,而不是回到第一幀,如果你希望動效播放完后組件的狀態復原到播放前,你可以最后添加一幀重新設置組件的狀態。高級用法: public void SetValue(string label, params object[] aParams) 改變指定幀的數值,例如某幀Label為aa,這幀是設置某個元件的XY值的,那么調用setValue(aa, 100,200)就可以將原來此幀設置XY的數值改為100,200。 public void SetHook(string label, TransitionHook callback) 可以設定運行到某幀時發生一個調用。多國語言支持 2、運行時動態加載語言文件。這種方法相對比較靈活。 Unity代碼片段: string fileContent; //自行載入語言文件,這里假設已載入到此變量 FairyGUI.Utils.XML xml = new FairyGUI.Utils.XML(fileContent); UIPackage.SetStringsSource(xml);(十二)UI適配策略 (分辨率 設置) GRoot.inst.setContentScaleFactor(設計分辨率寬度,設計分辨率高度,適配策略); someComponent.setSize(GRoot.inst.width, GRoot.inst.height);// 滿屏GRoot是FairyGUI的根組件,它的大小與屏幕分辨率的關系為 GRoot.inst.width = 屏幕寬度/GRoot.contentScaleFactor; GRoot.inst.height = 屏幕高度/GRoot.contentScaleFactor;(十三)顯示架構API FairyGUI在原生的渲染引擎上封裝了一層顯示對象結構。 基礎類顯示對象: GObject:顯示對象的基類。 GGraph:圖形對象。對應于編輯器中顯示的一個圖形。 GImage:圖片對象。對應于編輯器中顯示的一個圖片。 GMovieClip:動畫對象。對應于編輯器中顯示的一個動畫。 GLoader:裝載器對象。對應于編輯器中顯示的一個裝載器。 GTextField:文本對象。對應于編輯器中顯示的一個文本。 GRichTextField:多媒體文本。對應于編輯器中顯示的一個多媒體文本。 GTextInput:輸入文本對象。對應于編輯器中顯示的一個文本,且文本類型被設置為“輸入”。 容器類顯示對象: GComponent:組件對象。對應于編輯器中創建的一個組件。 GList:列表對象。對應于編輯器中顯示的一個列表。 容器的擴展: GLabel:標簽對象。當一個組件的擴展為“標簽”時,即為此類型。 GButton:按鈕對象。當一個組件的擴展為“按鈕”時,即為此類型。 GComboBox:組合框對象。當一個組件的擴展為“組合框”時,即為此類型。 GScrollBar:滾動條對象。當一個組件的擴展為“滾動條”時,即為此類型。 GProgressBar:進度條對象。當一個組件的擴展為“進度條”時,即為此類型。 GSlider:滑動條對象。當一個組件的擴展為“滑動條”時,即為此類型。 FairyGUI和Flash/Cocos類似,采用樹狀的結構組織顯示對象。容器可以包含一個或多個基礎顯示對象,也可以包含容器。這個樹狀結構稱為顯示列表。如下圖:處于最前面的且元件范圍包含點擊位置的元件將捕獲鼠標或觸摸事件,并且開始冒泡傳遞(請參考事件系統 Flash/Starling/Egret/Unity) 對于組件(GComponent),寬度x高度的范圍內點擊檢測都是有效的,無論這個范圍內是否有子元件。舉個例子說明。組件A和組件B分別為:將B先添加進舞臺,然后再添加A到舞臺,也就是說,A顯示B的前面,效果如下圖:可以看到,雖然A在B的上面,但紅色方塊是可見的,因為A在此區域并沒有內容。當點擊圖中綠色點的位置時,點擊事件將在A上面觸發,而B是點擊不了的。這是因為在A的范圍內,點擊是不能穿透的。 如果希望A能被穿透應該怎樣?可以通過GComponent.opaque屬性設定。當設定為false時,這個組件將能被穿透。例如A.opaque=false,這時,只有點擊4個白塊時,A才接收到點擊事件,如果點擊綠色點位置,B將接收到點擊事件。這個特性在設計一些全屏界面時尤其要注意。也可以在編輯器里直接設定:滾動支持 你可以在編輯器里很方便的對一個組件添加滾動特性。如果一個組件在編輯器里設置為滾動,我們可以通過GComponent.scrollPane獲得滾動控制對象。 ScrollPane提供了多個API訪問和控制滾動: ScrollPane.percX/ScrollPane.percY:獲得或設置當前滾動的位置,以百分比來計算,取值范圍是0-1。如果希望滾動條從當前值到設置值有一個動態變化的過程,可以使用ScrollPane.setPercX和ScrollPane.setPercY,這兩個API提供了一個是否使用緩動的參數。 ScrollPane.posX/ScrollPane.posY:獲得或設置當前滾動的位置,以像素來計算。取值范圍決定于當前顯示的內容大小與視口大小的差別。例如,一個垂直滾動的組件,如果視口大小為100像素,實際內容大小為300像素,那么posY的取值范圍是0~200像素,當posY=200時,滾動條滾動到最下方。posX/posY與percX/percY不同在于,除非開發者自己設置或者用戶拖動滾動條,percX/percY是不變的,舉個例子,當前某滾動容器的percX=0.1, posX=100,如果往容器里添加一定內容后,內容的寬度增大,percX的值仍將保持不變,依然是0.1,但posX的值會發生相應的改變。所以如果希望容器內增刪內容后滾動條不發生滾動,可以先記錄posX/posY的位置,添加完之后再設置posX/posY為此前記錄的位置。 ScrollPane.scrollToView:調整滾動位置,使指定的元件出現在視口內。 窗口系統 窗口使用前首先要設置窗口中需要顯示的內容,這通常是在編輯器里制作好的,可以直接使用Window.contentPane進行設置。建議把設置contentPane等初始化操作放置到Window.onInit方法中。 另外,FairyGUI還提供了一套機制用于窗口動態創建。動態創建是指初始時僅指定窗口需要使用的資源,等窗口需要顯示時才實際開始構建窗口的內容。首先需要在窗口的構造函數中調用Window.addUISource。這個方法需要一個IUISource類型的參數,而IUISource是一個接口,用戶需要自行實現載入相關UI包的邏輯。當窗口第一次顯示之前,IUISource的加載方法將會被調用,并等待載入完成后才返回執行Window.OnInit,然后窗口才會顯示。 調用Window.show顯示窗口的流程:如果你需要窗口顯示時播放動畫效果,那么覆蓋doShowAnimation編寫你的動畫代碼,并且在動畫結束后調用onShown。 覆蓋onShown編寫其他需要在窗口顯示時處理的業務邏輯。 調用Window.hide隱藏窗口的流程:如果你需要窗口隱藏時播放動畫效果,那么覆蓋doHideAnimation編寫你的動畫代碼,并且在動畫結束時調用Window.hideImmediately(注意不是直接調用onHide!)。 覆蓋onHide編寫其他需要在窗口隱藏時處理的業務邏輯。 通常窗口會包括一個可用于拖動的標題欄,關閉按鈕等。我們在編輯器創建窗口組件時,可以為它創建一個名稱為frame的組件,frame組件的擴展應該選擇為“標簽”,這樣外部組件能夠為其設置圖標和標題屬性。frame組件中約定的內容還包括: closeButton:一個名稱為closeButton的按鈕將自動作為窗口的關閉按鈕。 dragArea:一個名稱為dragArea的圖形(類型設置為空白)將自動作為窗口的檢測拖動區域,當用戶在此區域內按住并拖動時,窗口隨之被拖動。 contentArea:一個名稱為contentArea的圖形(類型設置為空白)將作為窗口的主要內容區域,這個區域只用于Window.showModalWait。當調用Window.showModalWait時,窗口會被鎖定,如果設定了contentArea,則只鎖定contentArea指定的區域,否則鎖定整個窗口。如果你希望窗口在modalWait狀態下依然能夠拖動和關閉,那么就不要讓contentArea覆蓋標題欄區域。 注意以上的約定均為可選,是否含有組件frame,或者組件frame里是否含有約定的功能組件,并不會影響窗口的正常顯示和關閉。 Popup管理 在UI系統中我們經常需要一些彈出一些組件,這些組件在用戶點擊空白地方的情況下就會自動消失,又或者由開發者控制消失。GRoot提供了幾個API管理這些Popup組件。 GRoot.showPopup:彈出一個組件,如果指定了目標,則會調整彈出的位置到目標的下方,形成一個下拉的效果。同時提供了參數可以用來指定是向上彈出或者向下彈出。 GRoot.hidePopup: 默認情況下,用戶點擊空白地方就會自動關閉彈出的組件。也可以調用此API手工關閉。不指定參數時,所有當前的彈出都關閉。 FairyGUI會根據組件的大小自動計算彈出位置,以確保組件顯示不會超出屏幕。(十五)事件系統:Unity 發表回復 Unity平臺參考了Flash的事件機制,設計了自己獨特的事件系統。EventDispatcher是事件分發的中心,GObject就是一個EventDispatcher。每個事件類型都對應一個EventListener,接收事件并調用處理函數。例如需要編寫某個元件單擊的處理邏輯: aObject.onClick.Add(aCallback); void aCallback() { //some logic } 事件回調函數 每個事件可以注冊一個或多個回調函數。函數原型為: public delegate void EventCallback0(); public delegate void EventCallback1(EventContext context); 函數可以不帶參數或帶一個參數。 EventContext EventContext是回調函數的參數類型。 EventContext.sender:獲得事件的分發者。 EventContext.initiator:獲得事件的發起者。一般來說,事件的分發者和發起者是相同的,但如果事件已發生冒泡,則可能不相同。參考下面冒泡的描述。 EventContext.type:事件類型。 EventContext.inputEvent:如果事件是鍵盤/觸摸/鼠標事件,通過訪問inputEvent對象可以獲得這類事件的相關數據。 EventContext.data:事件的數據。根據事件不同,可以有不同的含義。 事件冒泡和事件捕獲 一些特殊的事件,比如鼠標/觸摸事件,具備向父組件傳遞的特性,這個傳遞過程叫做冒泡。例如當手指接觸A元件時,A元件觸發TouchBegin事件,然后A元件的父組件B觸發TouchBegin事件,然后B的父組件C也觸發TouchBegin事件,以此類推,直到舞臺根部。這個設計保證了所有關聯的顯示對象都有機會處理觸摸事件,而不只是最頂端的顯示對象。 冒泡過程可以被打斷,通過調用EventContext.StopPropagation()可以使冒泡停止向父組件推進。 從上面的冒泡過程可以看出,事件處理的順序應該是:A’s listeners->B’s listeners->C’s listeners,這里還有一種機制可以讓鏈路上任意一個對象可以提前處理事件,這就是事件捕獲。事件捕獲是反向的,例如在上面的例子中,就是C先捕獲事件,然后是B,再到A。所以所有事件處理的完整順序應該是: C’s capture listeners->B’s capture listeners->A’s capture listeners->A’s listeners->B’s listeners->C’s listeners 捕獲傳遞鏈是不能中止的,冒泡傳遞鏈可以通過StopPropagation中止。 事件捕獲的設計可以使父元件優于子元件和孫子元件檢查事件。 并非所有事件都有冒泡設計,請參考下面關于各個事件的說明。并非只有冒泡事件才有捕獲設計。在非冒泡事件中,capture的回調優于普通回調,僅此而已,可以作為一個優先級特性來使用。 InputEvent 對鍵盤事件和鼠標/觸摸事件,可以通過EventContext.inputEvent獲得此類事件的相關數據。InputEvent.x/InputEvent.y:鼠標或手指的位置;這是舞臺坐標,因為UI可能因為自適配發生了縮放,所以如果要轉成UI元件中的坐標,要使用GObject.GlobalToLocal轉換。 InputEvent.keyCode:按鍵代碼; InputEvent.modifiers:參考UnityEngine.EventModifiers。 InputEvent.mouseWheelDelta:鼠標滾輪滾動值。 InputEvent.touchId:拖動使用手指;在PC平臺,該值為0,沒有意義。 InputEvent.isDoubleClick:是否雙擊。 EventListener EventListener.Add/EventListener.Remove:添加或刪除一個回調,回調函數可以帶一個參數或者不帶參數。參數的類型是object,它的實際含義隨不同事件不同而不同; EventListener.AddCapture/EventListener.RemoveCapture:添加或刪除一個捕獲期回調。 事件類型 GObject.onClick:單擊。冒泡事件。事件數據為InputEvent對象。 GObject.onRightClick:右鍵單擊。冒泡事件。事件數據為InputEvent對象。 GObject.onTouchBegin:鼠標或手指按下。冒泡事件。事件數據為InputEvent對象。 GObject.onTouchEnd:鼠標或手指釋放。冒泡事件。事件數據為InputEvent對象。 GObject.onRollOver:鼠標移入元件。事件數據為InputEvent對象。 GObject.onRollOut:鼠標移出元件。事件數據為InputEvent對象。 GObject.onAddedToStage:元件被添加到舞臺。無事件數據。 GObject.onRemovedFromStage:元件從舞臺移出。無事件數據。 GObject.onKeyDown:元件接收到按鍵事件。只有獲得焦點的情況下才能接收按鍵事件。冒泡事件。事件數據為InputEvent對象。 GObject.onClickLink:文本中的鏈接被點擊。事件數據為href值,字符串類型。 GObject.onPositionChanged:元件的位置改變。無事件數據。 GObject.onSizeChanged:元件的大小改變。無事件數據。 GObject.onDragStart/GObject.onDragEnd:拖動是指玩家按住元件拖動然后釋放的過程。注意只有設置了GObject.draggable屬性的元件才會觸發拖動事件。拖動過程中可以獲得兩個通知:開始和結束。當onDragStart中,調用EventContext.PreventDefault()可以立刻取消拖動。無事件數據。 GTextField.onFocusIn/GTextField.onFocusOut:只有輸入類型的文本才會觸發這個事件。當輸入文本獲得焦點時,在移動設備上會彈出小鍵盤。無事件數據。 GTextField.onChanged:只有輸入類型的文本才會觸發這個事件。無事件數據。 GMovieClip.onPlayEnd:動畫設定的播放次數已經播放完畢。無事件數據。 GList.onClickItem:當GList容器內的元件被點擊時觸發的事件類型;事件數據為當前點擊的GObject對象。 GComponent.onScroll:如果容器是滾動類型容器,則滾動發生時產生該事件。 GComponent.onDrop:注意要和普通拖動區別,一個元件被拖動并釋放后并不會觸發Drop事件。Drop事件需配合DragDropManager使用。當DragDropManager拖動的圖標在某個元件上釋放時,這個元件就會觸發onDrop。事件數據為DragDropManager.StartDrag中傳遞的source值。 GButton.onChanged:當單選或者多選按鈕選中狀態改變時會觸發該事件(只有在用戶點擊后狀態改變才會觸發,如果是程序改變不會觸發)。無事件數據。 GComboBox.onChanged:當用戶從下拉列表中選擇一項時觸發該事件。無事件數據。 GSlider.onChanged:當用戶拖動滑塊改變Slider的值時觸發該事件。無事件數據。 Controller.onChanged:當控制器頁面改變會觸發該事件(改變selectedIndex會觸發該事件,setSelectedIndex則不會)。無事件數據。(十八)在Unity項目中使用FairyGUI 1. 使用UIPanel 只需3步就可以使用將編輯器中制作好的界面放入到Unity的場景中。第一步,從GameObject菜單中選擇FairyGUI->UIPanel:第二步,在Inspector里點擊PackageName或者ComponentName,將彈出選擇組件的窗口:第三步:這個窗口里列出了所有工程里能找到的UI包,選擇一個包和組件,然后點擊OK。可以看到,UI組件的內容顯示出來了。(注意:Unity4版本目前不支持顯示內容,只能顯示線框) 如果UI包修改了,或者其他一些情況導致UIPanel顯示不正常,可以使用下面的菜單刷新:當運行后,獲得UIPanel的UI的方式是: UIPanel panel = gameObject.GetComponent(); GComponent view = panel.ui; 與其他UIPackage.CreateObject創建出來的界面不同,UIPanel在GameObjec銷毀時(手動銷毀或者過場景等)時會一并銷毀。 UIPane只保存了UI包的名稱和組件的名稱,它不對紋理或其他資源產生任何引用,也就是UI使用的資源不會包含在場景數據中。 在編輯狀態下,無論UI組件引用了哪些UI包的資源,包括放置在Resources目錄下的和不放置在Resources下的,都能夠正確顯示。但當運行后,UIPanel只能自動載入放置在Resources目錄或其子目錄下的UI包,也只會載入自身所在的UI包,其他情況的UI包(例如引用到的UI包或打包到AssetBundle的UI包)不能自動載入。你需要在UIPanel創建前使用UIPackage.AddPackage準備好這類UI包。UIPanel在Start事件或者第一次訪問UIPanel.ui屬性時創建UI界面,你仍然有機會在Awake里完成這些操作。 下面是UIPanel的一些屬性說明: Render Mode: 有三種: Screen Space Overlay (默認值),表示這個UI在屏幕空間顯示,這時Transform的Scale將被鎖定,而且不建議修改Transform中的其他內容(讓他們保持為0)。如果要修改面板在屏幕上的位置,使用UI Transform(參考下面關于UI Transform的說明)。 Screen Space Camera 表示這個UI在屏幕空間顯示,但不使用FairyGUI默認的正交相機,而是使用指定的正交相機。 World Space 表示這個UI在世界空間顯示,由透視相機渲染。默認的使用場景的主相機,如果不是,那么設置Render Camera。當使用這種模式時,使用Transfrom修改UI在世界空間中的位置、縮放、旋轉。但你仍然可以使用UI Transform。 注意:Render Mode只定義了FairyGUI對待這個UI的方式,通常是坐標相關的操作(如點擊檢測等),但和渲染無關。UI由哪個相機渲染是由GameObject的layer決定的。所以如果發現UI沒有顯示出來,可以檢查一下GameObject的layer是否正確。例如如果是Screen Space,GameObject應該在UI層,如果是WorldSpace,則是在Default層或者其他自定義的層次。 Render Camera:當Render Mode是Screen Space Camera或者World Space時可以設置。如果不設置,默認為場景的主相機。 Sorting Order:調整UIPanel的顯示順序。越大的顯示在越前面。 Fairy Batching:是否啟用Fairy Batching。關于Fairy Batching請參考下面的說明。切換這個值,可以在編輯模式下實時看到DrawCall的變化(切換后點擊一下Game,Stat里顯示的內容才會更新),這可以使你更加容易決定是否啟用這項技術。 Touch Disabled:勾選后,將關閉點擊檢測。當這個UI沒有可交互的內容時可以勾選以提高點擊檢測時的性能。例如頭頂血條這些類型的UI,就可以勾選。 UI Transform:當Render Mode是Screen Space時可以使用這里的設置調整UI在屏幕上的位置。你仍然可以調整Transform改變UI的位置,但我不建議你這樣做,因為Transform中的坐標位置是沒有經過不同分辨率自適應的調整的。當Render Mode是World Space時,建議使用Transform設置UI的位置,你仍然可以調整UI Transform改變UI的位置,但調整的效果可能不那么直觀。同時你可以使用Scene視圖中下圖所示的原點調整UI Transform的位置屬性:Fit Screen:這里可以設置UIPanel適配屏幕。 Fit Size:UI將鋪滿屏幕。 Fit Width And Set Middle:UI將橫向鋪滿屏幕,然后上下居中。 Fit Height And Set Center:UI將縱向鋪滿屏幕,然后左右居中。 這里提供的選項不多,因為FairyGUI推薦的是在FairyGUI編輯器中整體設計,而不是在Unity里擺放小元件。例如如果需要不同的UI在屏幕上的各個位置布局,你應該在FairyGUI編輯器中創建一個全屏大小的組件,然后在里面放置各個子組件,再用關聯控制布局;最后將這個全屏組件放置到Unity,將Fit Screen設置為Fit Size即可。錯誤的做法是把各個子組件放置到Unity里再布局。 HitTest Mode:這里可以設置UIPanel處理鼠標或觸摸事件的方式。 Default: 這是默認的方式。FairyGUI會用內置的機制檢測鼠標或觸摸動作,不使用射線,UIPanel也不需要創建碰撞體,效能比較高。 Raycast: 在這種方式下,UIPanel將自動創建碰撞體,并且使用射線方式進行點擊檢測。這種方式適合于UIPanel還需要和其他3D對象互動的情況。 2. 動態載入UI界面 在很多情況下,你并不需要將UI界面放到場景中。使用代碼載入編輯器制作好的界面也非常簡單: GComponent view = UIPackage.CreateObject(“包名”, “組件名”) as GComponent 動態載入的界面不會自動銷毀,例如一個背包窗口,你并不需要在每次過場景都銷毀。如果要銷毀界面,調用Dispose方法即可,例如 view.Dispose(); 也可以動態創建UIPanel為任意游戲對象掛接UI界面,方法為: UIPanel panel = yourGameObject.AddComponent(); panel.packageName = “包名”; panel.componentName = “組件名”; panel.CreateUI(); UIPanel的生命周期將和yourGameObject保持一致。再次提醒,注意yourGameObject的layer。 3. 載入UI包 Unity項目載入UI包有以下幾種方式,開發者可以根據項目需要選擇其中一種或者多種混搭使用: 1)將打包后的文件直接發布到Unity的Resources目錄或者其子目錄下,然后在代碼中調用UIPackage.AddPackage(“demo”), demo就是發布時填寫的文件名。如果在子目錄下,調用UIPackage.AddPacakge(“路徑/demo”)即可。 2)將發布后的文件打包為兩個AssetBundle,即定義文件和資源各打包為一個bundle(desc_bundle+res_bundle)。這樣做的好處是一般UI的更新都是修改元件位置什么的,不涉及圖片資源的更新,那么只需要重新打包和推送desc_bundle就行了,不需要讓玩家更新通常體積比較大的res_bouble,節省流量。打包程序由開發者按照自己熟悉的方式自行實現。以demo為例,請遵循以下規則打包: a)demo.bytes單獨打包為desc_bundle; b)其他資源(demo@atlas0.png等),打包到res_bundle(在此例中就是atlas0和sprites) 然后在代碼中調用UIPackage.AddPackage(desc_bundle, res_bundle)。bundle的載入由開發者自行實現。 3)將發布后的文件打包為一個AssetBundle。打包程序由開發者按照自己熟悉的方式自行實現。以demo為例,將demo.bytes和其他資源(demo@atlas0.png等),都放入bundle。然后在代碼中調用UIPackage.AddPackage(bundle, bundle)。bundle的載入由開發者自行實現。 在使用AssetBundle的載入方案中,將由FairyGUI接管bundle并負責bundle資源的釋放。 4. UI適配 可以通過兩種方式設置UI自適應,第一種方式是在游戲的啟動創建里任意對象掛一個FairyGUI/UIContentScaler組件:這里選項的含義可以參考教程里關于UI適配的說明。 另外一種方式是通過代碼,可以參考教程里關于UI適配的說明。 5.圖集的處理 FairyGUI編輯器發布到Unity的資源通常包含一個或多個UI圖集,以demo工程為例,這里demo@atlas0.png就是一個圖集圖集是由UI編輯器自動生成的,但在Unity里可以改變圖集的屬性,常用的設置有: 1)Generate Mip Maps 不勾選。UI不使用Mip Maps功能。 2)Filter Mode 使用Bilinear,這樣圖像在縮放時能產生比較平滑的過渡效果,副作用是會產生一定的模糊。而且單色的圖像縮放會產生不必要的漸變邊緣。而使用Point,則圖像在縮放時會塊狀化。一般UI圖集使用Bilinear即可。你也可以在UI編輯器里將圖片安排到不同圖集,然后每個圖集設置不同的Filter Mode以滿足特殊需求。 3)Max Size 一般設置到2048。 4)Format UI圖集一般都是PNG格式,并帶有透明通道。同時,UI對畫質的要求比較高,所以建議選擇AutoMatic TrueColor。但TrueColor有一個最大的問題是文件大,而且占用內存較高,例如1024×1024的圖集,將占用4MB的內存,2048×2048則達到16MB。 如果對內存使用比較敏感,也可以選用壓縮格式,即AutoMatic Compressed。在桌面平臺上即相同于DXT5,在Android平臺上相當于ETC1,在IPhone平臺則為PVRTC。這些格式能夠大大降低內存占用,也因為它們是顯卡直接支持的格式,所以Unity在載入時省去了解碼位圖的步驟,能夠加快載入速度。但它們都是屬于有損壓縮,在顯示質量上肯定不如TrueColor,特別是圖集顏色十分豐富,或者有顏色漸變時,失真會比較厲害。特別重要的是,ETC1是不支持透明通道的,PVRTC對透明通道的支持也比較弱,所以并不適合帶透明通道的圖集。FairyGUI提供了ETC1/PVRTC+A的解決方案。首先,在發布時勾選“為Alpha通道創建單獨的貼圖”,如下圖:這樣,就產生了兩個不含透明通道的貼圖,一張去除了原圖透明通道的貼圖,和一張將原貼圖透明通道數值轉換為等價灰度的貼圖。這兩張貼圖都可以設置為Automatic Compressed。(一定要注意,不能再將主貼圖設置為True Color)FairyGUI提供了特制的著色器處理兩張貼圖的合并。開發者并不需要編寫額外的代碼就可以使用這項技術。 TIPS 你可以將本身就不含透明通道的位圖(例如一些大型的背景圖)安排到一張圖集上。如果一張圖集內的所有圖片都不包含透明通道,那么最終輸出的圖集也不包含透明通道。不含透明通道的圖集可以選用Automatic 16bits格式。 6. 字體的處理 FairyGUI使用Unity的動態字體技術渲染文字。只需以下幾個簡單的步驟就可以完成設置: 1)拷貝一個字體文件到項目的Resources目錄或Resources/Fonts目錄。字體文件可以隨意使用一個,例如arial.ttf,或simhei.ttf等,這個ttf是什么字體并不影響最終顯示字體的選擇。 2)在Unity中點擊字體文件,在inspector中修改字體屬性注意在Font Names中填寫的是字體名稱,標準的字體名稱可以從這里找到: 中文字體的英文名稱對照表。例如Droid Sans Fallback是Android平臺支持中文的內置默認字體之一。多個字體用逗號隔開,Unity會使用第一個在系統中能找到的字體。 3)設置UIConfig.defaultFont=”字體文件名稱”即可,注意這里使用的是文件名稱,也就是說,如果放置在Resources目錄的是arial.ttf,則UIConfig.defaultFont=”arial”,不需要帶.ttf后綴。 因為我們沒有勾選Include Font Data,所以無論這個字體文件有多大,最終并不會包含在我們的發布包中,也就是說不會增大發行包的體積。Unity會在實際運行的系統中查找與Font Names匹配的第一個字體,并使用此字體進行動態渲染。 如果你是在Unity5.x平臺開發,除了上述方式外,得益于Unity5.x引入的新的字體管理API,也可以不放置字體文件到Resources目錄,你只需要直接設置UIConfig.defaultFont=”字體名稱“即可,同樣,多個字體名稱用逗號隔開。例如:UIConfig.defaultFont=”Droid Sans Fallback, LTHYSZK, Helvetica-Bold, Microsoft YaHei, SimHei”; 4)如果你的界面使用了多種字體,比如對單獨的文字設置了字體:這里用到了“黑體”這個名字的字體,這是與UIConfig.defaultFont里設置的不同的字體,我們也需要注冊這種字體。方法是,首先做好上面1)和2),假如字體文件名稱是HeiTi.ttf,然后 FontManager.RegisterFont(“黑體”, FontManager.GetFont(“HeiTi”)); RegisterFont的第一個參數對應編輯器里使用的字體名稱;第二個參數,是Unity中放入的字體文件資源。如果文件帶路徑,這也需要把路徑填上。 5)當你使用部分字體的粗體效果時,你會發現粗體的效果在Unity中的顯示不正確,這是因為有些字體不帶粗體效果的,這時候Unity就會用拉寬來實現,就像變扁了。fairygui可以用額外的mesh來解決粗體的顯示。方法是: FontManager.GetFont(“字體路徑”).customFold = true; 這里字體路徑與UIConfig.default里設置的內容應該完全一樣。 6)某些字體,unity渲染有粗體效果,但當設置成斜體時,粗體效果又丟失(例如雅黑)。fairygui在這種情況取消unity默認渲染粗體的效果,改為增加額外的面渲染粗體。激活這個功能的方法是 FontManager.GetFont(“字體路徑”).customBoldAndItalic = true; 如果已經設置了customBold,不需要再設置customBoldAndItalic。 備注1 動態字體要求玩家的運行系統環境中有你設定的字體,如果沒有,實際使用的字體可能并不是你想要的效果。因此,你可以選擇嵌入整個字體文件。方法是把你要用的字體文件放到Resources目錄,并把Include Font Data勾選,這樣整個字體文件就會包含到最終的發布包中,壞處就是會大大增加發行包的體積。 備注2 在實際游戲制作過程中發現在桌面平臺下Unity對中文字體的渲染稍顯模糊和暗淡,因此FairyGUI使用了特制的著色器解決了這個問題。以下是Unity默認的字體渲染效果和FairyGUI的字體渲染效果的比較:可以看見經過FairyGUI的特殊處理,中文文字更清晰更亮。 只有在桌面平臺下FairyGUI才會開啟這種技術,移動平臺永遠不會開啟,因為在高DPI情況下,字體默認的渲染效果已經非常漂亮。 另外,如果你不喜歡這種顯示效果,或者你使用的是全英文的文字,也可以手動把這種技術關閉:UIConfig.renderingTextBrighterOnDesktop = false; 7 在UI中穿插其他3D對象 FairyGUI底層使用Renderer.sortingOrder來決定對象的渲染順序,利用這個特性,我們可以很容易的將UI對象與其他3D對象(例如例子)安排在一起。FairyGUI提供了封裝類GoWrapper,可以直接包裝其他GameObject插入到UI層次中。如下圖,一個粒子特效被安排到了UI之間。又例如,一個3D模型穿插在UI中間詳細實現方法可以參考FairyGUI-unity包中的Assets/FairyGUI/Examples/Particles和Assets/FairyGUI/Examples/Model。 8. 與RenderTexture配合 在UI上展現3D內容的另一種方式是使用RenderTexture,特別是需要進行剪裁的情況下(如果不需要剪裁,推薦直接放置3D內容,免除RenderTexture性能消耗。參考6. 在UI中穿插其他3D對象)。在FairyGUI中,可以將Image.texture設置為一個RenderTexture,然后就可以像使用普通圖片一樣使用這個RenderTexture了,可以出現在任何地方,包括滾動容器。特別地,FairyGUI還能支持將RenderTexture所在位置的背景圖片影射到RenderTexture渲染相機的背景上,這樣就不用擔心透貼的問題了。如下圖,NPC使用RenderTexture渲染到UI窗口中。詳細實現方法可以參考FairyGUI-unity包中的Assets/FairyGUI/Examples/RenderTexture。 9. Drawcall優化 在Unity中,每次引擎準備數據并通知GPU的過程稱為一次Draw Call(DC)。Draw Call次數是一項非常重要的性能指標。UI系統一般包含數量眾多的物體,有效控制DC是衡量一個UI系統是否實用的關鍵因素,特別是在移動設備上。 我們先來看看NGUI是怎么做的,NGUI把UIPanel中的Widget按depth排序,然后將相同材質的Widget進行Mesh合并,例如使用相同圖集的圖片,或者文字。Mesh合并的優點是合并后這些Widget就只產生一個DC。但這個合并過程需要計算所有Widget坐標相對于Panel的變換,而且如果Widget行為改變,例如平移,縮放等,都會觸發Mesh重新合并,這會帶來一定的CPU消耗,這就需要開發者謹慎組織UI元素到各個UIPanel,并且對深度需要細致安排,否則達不到減少DC效果的同時更可能帶來比較大的CPU消耗。 FairyGUI沒有采取合并Mesh的策略,原因有兩個: ● FairyGUI使用的是樹狀顯示對象結構,各個元件之間的層次關系非常復雜; ● FairyGUI編輯器給予用戶最大的設計自由度,加上動效的引入,各個元件的狀態都可能非常動態; FairyGUI基于Unity的Dynamic Batching技術,提供了深度調整技術進行 drawcall優化 。FairyGUI能在不改變最終顯示效果的前提下,盡可能的把相同材質的物體調整到連續的renderingOrder值上,以促使他們能夠被Unity Dynamic Batching優化。Dynamic Batching是Unity提供的Draw Call Batching技術之一。如果動態物體共用著相同的材質,那么Unity會自動對這些物體進行批處理。但Dynamic Batching的一個重要的前提是這些動態物體是連續渲染的。先來看看FairyGUI中物體的渲染順序,例如:這里有4個按鈕,每個按鈕都是一個組件,每個組件里包含一個圖片和一個文字對象。FairyGUI是樹狀的顯示對象結構,那么他們按深度排序應該是:因為文字和圖片的材質并不相同,所以每次從文字到圖片都產生上下文切換,所以產生了6個DC。 FairyGUI的深度調整技術可以優化這種情況。觀察一下,其實四個按鈕之間并不相交,所以FairyGUI智能地將渲染順序調整為:因為FairyGUI使用了圖集,而且動態文字也使用了相同的貼圖,這樣,DC就降低到了2個,達到了優化的目的。實際情況會比這個復雜很多,但FairyGUI能在不改變最終顯示效果的前提下,盡可能的把相同材質的物體調整到連續的renderingOrder值上,以促使他們能夠被Unity Dynamic Batching優化。而對開發者來說,這些底層上的調整是透明的,也就是不會影響原來的顯示對象層次。從效率上考慮,這種技術僅比較物體之間的顯示矩形區域(一個Rect)是否相交,所以速度是非常快的,不會帶來過多的CPU負荷。 FairyGUI提供了一個開關控制組件是否啟用深度調整,API是: GComponent someComponent; someComponent.fairyBatching = true; 如果某個組件設置了fairyBatching,那么無需在子組件和孫子組件再啟用fairyBatching。一般只在頂層組件打開這個功能,例如主界面,加載界面等。注意,Window這個類已經自動打開了fairyBatching,這符合我們的使用習慣,因為一般我們都是以窗口為單位安排功能的。如果界面不復雜,Draw Call本來就不高的情況下,開發者也可以忽略這個功能,從10個DC優化到8個DC并沒有什么意義。在實際使用過程中, 對于打開了fairyBatching的組件,當開發者動態改變子元件或者孫子元件的位置或大小時,并不會自動觸發深度調整,例如一個圖片原來顯示在一個窗口里的頂層,你用Tween將它從原來的位置移到另外一個位置,這個圖片就有可能被窗口里的其他元素遮擋。這時開發者可以手動觸發深度調整,API是 someObject.InvalidateBatchingState(); 這個API并不需要由開啟了fairyBatching的組件調用,它可以用任何一個內含的元件發起。對于UI動效(Transitions),FairyGUI已經自動調用了這個API,所以開發者不必處理。 下載并運行Demo,可以觀察fairyBatching的實際效果。例如這個Demo的首頁:設置了fairyBatching后由42個DC減少到了6個DC,另外,可以看到Saved by batching: 27的字樣。與ULUA配合 一、安裝 1、將以下語句添加到Assets\uLua\Editor\WrapFile.cs適當的位置,然后調用Lua的菜單Gen Lua Wrap Files,重新生成綁定文件。 _GT(typeof(EventContext)), _GT(typeof(EventDispatcher)), _GT(typeof(EventListener)), _GT(typeof(InputEvent)), _GT(typeof(DisplayObject)), _GT(typeof(Container)), _GT(typeof(Stage)), _GT(typeof(Controller)), _GT(typeof(GObject)), _GT(typeof(GGraph)), _GT(typeof(GGroup)), _GT(typeof(GImage)), _GT(typeof(GLoader)), _GT(typeof(PlayState)), _GT(typeof(GMovieClip)), _GT(typeof(TextFormat)), _GT(typeof(GTextField)), _GT(typeof(GRichTextField)), _GT(typeof(GTextInput)), _GT(typeof(GComponent)), _GT(typeof(GList)), _GT(typeof(GRoot)), _GT(typeof(GLabel)), _GT(typeof(GButton)), _GT(typeof(GComboBox)), _GT(typeof(GProgressBar)), _GT(typeof(GSlider)), _GT(typeof(PopupMenu)), _GT(typeof(ScrollPane)), _GT(typeof(Transition)), _GT(typeof(UIPackage)), _GT(typeof(Window)), _GT(typeof(GObjectPool)), _GT(typeof(Relations)), _GT(typeof(RelationType)), 2、拷貝FairyGUI.lua到你的lua文件存放目錄。 二、使用 1、普通方法的偵聽和刪除偵聽 require ‘FairyGUI’ function OnClick() –也可以帶上事件參數,OnClick(context) print(‘you click’) end UIPackage.AddPackage(‘Demo’) local view = UIPackage.CreateObject(‘Demo’, ‘DemoMain’) GRoot.inst:AddChild(view) view.onClick:Add(OnClick) –view.onClick:Remove(OnClick) 2、類方法的偵聽和刪除偵聽 require ‘FairyGUI’ TestClass = class(‘TestClass’, {}) function TestClass:ctor() UIPackage.AddPackage(‘Demo’) self.view = UIPackage.CreateObject(‘Demo’, ‘DemoMain’) GRoot.inst:AddChild(self.view) self.view.onClick:Add(TestClass.OnClick, self) –self.view.onClick:Remove(TestClass.OnClick, self) end function TestClass:OnClick() –也可以帶上事件參數,TestClass:OnClick(context) print(‘you click’) end TestClass.New() 3、如果要使用Tween,你可以直接使用GObject.TweenXXXX系列函數,免除了Wrap DOTween的麻煩。
總結
以上是生活随笔為你收集整理的FGUI的常用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。