UGUI筆記


  • Text中的可以單獨指定某些文字的顏色,只需將想要變色的文本放在<color=**></color>之間即可,如“吃<color=#ff7a38>橙色物品</color>有機會獲得<color=red>紅色寶石</color>”,同樣適用於NGUI。
  • 兩張圖片,如頭像框,頭像在背景圖之上,頭像會擋住背景的點擊事件,要實現全框的點擊效果,只需要將頭像作為背景的子物體就可以了。當然頭像上不能有Button組件。
  • 自帶的CanvasGroup組件可以實現屏蔽其下所有UI的點擊等事件觸發,也可以實現整休改變所有子UI的alpha透明度。
  • RectMask2D,類似Mask,但:

    the limitations of RectMask2D control are:

    • It only works in 2D space
    • It will not properly mask elements that are not coplanar

    The advantages of RectMask2D are:

    • It does not use the stencil buffer
    • No extra draw calls
    • No material changes
    • Fast performance
  •  Content Size Fitter組件:自動改變RectTransfrom的size大小。如Text根據文字內容的長短自動縮放控件本身的大小,如一個ScrollRect下的Grid中的元素超時Rect時拖動無效的原因便是Grid未加上該組件它自身的大小未跟隨元素的增多而增大。
    注意自動變化寬高時的方向是根據Pivot的設置,若Pivot在中心時則會上下左右同時都會有縮放,若Pivot在頂部時則大小只會從底部放大或縮小。

  • Grid的使用:若元素(子物體)是大小一樣的則優先使用Grid Layout Group組件;若元素是大小不一的則選用Horizontal/Vertical layout Group並配合Layout Element組件。
    通過靈活組合ScrollRect、ContentSizeFitter、GridLayoutGroup、HorizontalLayoutGroup/VerticalLayoutGroup、LayoutElement、可以實現很復雜的動態增刪組合UI效果。
    詳見UGUI Auto Layout 自動布局http://www.manew.com/thread-95758-1-1.html
  • 避免使用布局分組(Layout Group,包括Grid,Scroll Rect等),使用錨點進行比例布局,或者考慮編寫代碼來計算布局,僅在需要時而不是每次發生改變時都計算。因為布局分組中有一個元素使布局變臟就會至少GetComponents一次且繼續遍歷Transform層級,有一定的開銷。
  • RectTransform的大小改變時有一個回調函數:OnRectTransformDimensionsChange。當ContentSizeFitter來自動調整RectTransform的大小時並不能立馬生效,而是需要到下一幀才能得到正確的大小,此時該回調便有用武之地了。然而該回調的觸發確有點奇怪會被觸發多次且有時觸發的次數還不同,另一解決辦法是在獲取RectTransform的size時調用LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);不過該接口要5.x版本才能用....

  • RectTransform的屬性說明:
    * anchorMin、anchorMax:這兩個點確定一個矩形,這個矩形的四個頂點就是錨點,為0-1之間,x邊的長度(anchorMax.x與anchorMin.x差值構成的邊,即矩形的寬度)占父RectTransform寬的比例和相對位置即為自身RectTransform水平方向相對父物體大小變化時的變化量(和局部坐標位置變化量),y垂直方向同理。
    當x邊(水平)或y邊(垂直)長度為1時,父物體在該方向大小改變時子物體大小(和局部坐標)按等比例變化;長度在0-1之內時,父物體大小變化量乘以該比例即為子物體大小變化量同時改變子物體局部坐標;長度0時,子物體大小不隨父物體大小改變,該值僅表示兩者的相對位置(為父物體在該方向上的大小變化量與子物體局部坐標變化量的比例值)。
    * anchoredPosition:中心點Pivot相對於錨點位置的坐標,若四個錨點未重合,則根據Pivot擺放信息在四個錨點中計算出錨點的參考位置,如中心點位於左下時,anchoredPosition為中心點相對於左下錨點的坐標。
    anchoredPosition為相對坐標,不會隨着父物體大小的改變而改變,會變的是localPosition。
    * sizeDelta:RectTransform的Rect矩形區域大小相對於四個錨點(點的坐標,不是anchorMin、anchorMax值)組成的矩形大小(anchorSize)的差量。僅當四個錨點重合時該大小等於RectTransform的大小,當四個錨點分別跟父RectTransform四角重合時,該值表示子大小相對於父大小的差值。
    anchorSize = parentRectTransform.rect.size * (anchorMax - anchorMin);
    //或者anchorSize = LerpUnclamped(parentRect.min, parentRect.max, anchorMin) - LerpUnclamped(parentRect.min, parentRect.max, anchorMax);(LerpUnclamped即對x和y坐標分別Lerp,不局限在0-1之前插值)
    sizeDelta = realSize(即rect.size) - anchorSize;
    以上即SetSizeWithCurrentAnchors的實現,可見sizeDelta的意義所在。
    * offsetMin、offsetMin:這兩個值是根據anchoredPosition和sizeDelta計算出來的值,表示RectTransform左下角相對左下錨點的坐標和右上角相對右上角錨點的坐標。
    sizeDelta大小等於offsetMax-offsetMin。
    想讓子物體跟父一樣大小且位置重合,可這樣修改:rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero;
    可以在不改中心點的情況下,向特定方向修改大小:修改offsetMin可以讓RectTransform向左下方向改變大小,修改offsetMax可以讓RectTransform向右上方向改變大小。
    * rect:RectTransform的矩形區域的數據表示。x、y為矩形左下角相對中心點的坐標,size即實際大小。該值為只讀的。
  • RectTransform的幾個API說明:
    * public void GetLocalCorners(Vector3[] fourCornersArray):傳入4個長度的Vector3數組,得到該RectTransform從左下開始到右下的四個角相對自身中心點Pivot的坐標,注意這並不是相對父物體的局部坐標,所以移動RectTransform時這4個坐標並不會發生變化。
    * public void GetWorldCorners(Vector3[] fourCornersArray):得到該RectTransform的四個角的世界坐標,不用關心當前及父對象的中心點及錨點的設置。
    * public void SetSizeWithCurrentAnchors(Axis axis, float size):設置RectTransform的寬或高,可以不用關心當前及父對象的中心點及錨點的情況而直接設置寬高。當anchor的四角合一時該函數便跟設置sizeDelta效果一樣。
    * public void SetInsetAndSizeFromParentEdge(Edge edge, float inset, float size):設置RectTransform相對父物體的某一邊緣的距離和寬高,同樣可以不關心當前及父對象的中心點及錨點的情況而直接設置位置和寬高。edge父物體的上下左右某一邊,inset為到edge邊的距離,size為要將RectTransform設置的寬度或高度,當edge為左右時size為寬度,當edge為上下時size為高度。注意該函數會根據edge改變RectTransform的anchor。
    如:rectTrans.SetInsetAndSizeFromParentEdge (RectTransform.Edge.Top, 200, 400);rt.SetInsetAndSizeFromParentEdge (RectTransform.Edge.Left, 100, 300);該兩次調用后rectTrans的高為400,上邊距離父物體的上邊為200,寬為300,左邊距離父物體的左邊為100。

  • 當UI和ParticleSystem特效混用時會出現類似NGUI中特效與UI顯示層級混亂的問題,如一個特效想要顯示在兩個UI之間或者一個UI的前面和后面各有一個特效時:
    首先Canvas不能為Overlay,需要指定Camera。
    然后UI1的Canvas的OrderInLayer為1,UI2的Canvas的OrderInLayer為3(可多個Canvas嵌套使用),Particle所在的Canvas的OrderInLayer為2。
    正常認為Particle應該位於兩個UI之間了,然而由於Particle默認是位於0層,通過設置之上的Canvas的層是不起作用的,故特效仍顯示不了。(針對半透明3D物體(放在Transparent隊列),在渲染上是關閉了ZWrite的(使用了Blend就會自動設置ZWrite Off),因此Unity采用了一種簡單的手段,將其強制放在缺省的Default Layer的Order in Layer(0)渲染(因此,對其掛Canvas是徒勞的))
    辦法1:由於Particle為0層,則讓需要顯示Particle之下的UI層設置為小於0的負數層級,顯示在Particle之上的UI則設置為大於0的層級數。這樣做有個問題是當同時有多個Particle,有的要顯示在UI之上有的要顯示在之下,即Particle需要位於不同層級時有問題。
    辦法2:設置Particle的層,在5.3版之后Particle本身Renderer可以直接設置層,但舊版本不行,增加腳本:
     1 public class SetOrder : MonoBehaviour
     2 {
     3     public int order;
     4 
     5     void Awake ()
     6     {
     7         Renderer[] renderers = GetComponentsInChildren<Renderer> ();
     8         for (int i = 0; i < renderers.Length; i++)
     9         {
    10             renderers[i].sortingOrder = order;
    11         }
    12     }
    13 }

    將需要設置Particle層的物體上掛上該腳本即可設置Particle的層了,如此各UI及特效都能自由設置層級關系了。同時多個Particle也可指定為同一個層級然后在代碼中設置renderer.material.renderQueue應該也是能調整特效之間的顯示層級的,未測試親可自測。

  • UGUI的Mask組件對Particle不起作用,解決辦法:
    創建兩個Shader,一個給粒子用,一個給UI Mask 用,兩個Shader的內容均采用Build-in Shader的Particle-Additive 和 UI-Default。利用Shader 的 Stencil 功能, 分別對兩個Shader加入以下內容:
    //UI Mask 
    Stencil
    {
    Ref 1
    Comp Always
    Pass Replace
    }
    //Paritcle
    Stencil {
    Ref 1
    Comp equal
    }
    之后分別創建相應材質球,將其賦予UIImage 和 想被遮罩的 Particle 即可。 如果看不見效果,調整一下Particle的位置。原文在評論區:http://www.xuanyusong.com/archives/3518
  • 代碼中主動調用UI事件以模擬點擊按鈕等操作:
    1 ExecuteEvents.Execute<IPointerClickHandler>(uiButton.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler);
    2 ExecuteEvents.Execute<ISubmitHandler>(uiButton.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.submitHandler);
  • 當按鈕圖片延Y軸旋轉180度(即背面在前,鏡像翻轉)時,按鈕點擊功能失效!同理推論所有UI元素只要背面在前時其點擊等所有事件都會失效。當有兩控件只是左右相反時想要共用一張圖就會出該問題。解決辦法是將點擊區域和圖片分離,在圖片上層放置一個透明圖片作為實際按鈕,按鈕的Target Graphic設置為翻轉后的圖片即可。新版可以設置Canvas上的GraphicRaycaster.ignoreReversedGraphics為false來禁用該功能解決。
  • 隱藏UI的方式:

    1.禁用Canvas組件,會阻止畫布向GPU發起繪圖調用,所以該畫布不再可見。然而,此時該畫布不會丟棄它的頂點緩沖區,它會保留所有網格和頂點,當重新啟用時不會觸發重構過程,它只會重新繪制畫布內容。

    此外,禁用Canvas組件不會觸發Canvas層級上性能消耗較大的OnDisable/OnEnable回調。

    2.SetActive(false)禁用根節點,整個UI都是未激活狀態,如果運行性能消耗較大的每幀代碼則可減少不必要開銷。

anchorMin、anchorMax


免責聲明!

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



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