国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

NGUI所見即所得之UIRoot

2019-11-09 17:30:13
字體:
來源:轉載
供稿:網友

 NGUI所見即所得之UIRoot

         

       UIRoot是NGUI最根本和最重要的腳本,在實際UI開發過程中都是以UIRoot為根的GameObject樹,那他的作用到底是什么,先看下UIRoot的Inspection選項:

看到這個,大致可以猜到是跟UI界面縮放有關的,而且是基于高度放縮的。

 

Scaling Style參數

 

       到底每個參數(Scaling Style, Manual Height ,Minimum Height 和MaximumHight)的作用和區別是什么,在沒有其他先驗知識的情況下,只有去看代碼了。

       

C#代碼  收藏代碼public enum Scaling      {          PixelPerfect,          FixedSize,          FixedSizeOnMobiles,      }  

       Scaling Style參數的作用是制定UIRoot的縮放類型,如果是PixelPerfect,Minimum Height和Maximum Height才起作用,換而言之,如果Scaling Style選擇的是PixelPerfect就要對Minimum Height和Maximum Height進行設置。FixedSize和FixedSizeOnMobiles只跟Manual Height有關,區別在于后者(FixedSizeOnMobiles)只是針對IOS和Android上的判斷,也就是說只有IOS和Android平臺下FixedSizeOnMobiles才起作用。

       那他們是怎么縮放的呢?如果是PixelPerfect縮放類型,當屏幕的分辨率大于Maximum Height,則以Maximum Height 為基礎縮放,反之,如果屏幕分辨率小于Minimum Height 則以Minimum Height為基礎進行縮放。例如,如果屏幕高度為1000,而設置的Maximum Height值為800,則UI界面整體放大為原來的1000/800=1.25倍。

       如果Scaling Style指定為FixedSize或FixedSizeOnMobiles,則縮放只以Manual Height為參考,屏幕分辨率的高度值不同于此設置值時,則根據其比例(即Screen Height / Manual Height)對整棵UI樹的進行“等比”縮放(寬度的縮放比也是此比例值)。

 

      如果Scaling Style指定為FixedSize,UIWidget.height(以UIRoot默認進行高度縮放)是不會改變的(有關UIWidget的內容可以查看D.S.Qiu的另外一篇文章),不管實際屏幕分辨率的像素是多少,這看下Example 1 的 Anchor Stretch的背景圖片,高度始終都是800,即設置的的manualHeight:        也就是相當于UIRoot下的UIWidget的height參數一直都是實際的值,雖然在實際在顯示器顯示的高度不是UIWidget.height這個值,所以才有了放縮的感覺。實際的放縮是根據Camera.pixelHeight(這個值和Screen.height的大小是一樣的)來的,也就是放縮比 = Camera.pixelHeight/UIRoot.manualHeight,或者是Screen.height/UIRoot.manualHeight。

         也就是說,當Scaling Style 指定為FixedSize,UIRoot的子對象高度的參數保持不變,至于顯示的縮放是根據Camera自動進行的,程序無需額外控制。更多詳細的分享可以參考另外一篇有關UIAnchor 和UIStretch的文章(猛點查看)。

                                                                                                                                           增補于 2013/11/16 14:20

 

Scaling Style策略       

 

(1)PixelPerfect和Minimum Height, Maximum Height

使用PixelPefect,只要是想達到UI圖片盡可能不縮放,保持原尺寸大小,這種在PC端這種可以調節界面大小的會使用比較多。

(2)FixedSize和Manul Height

FixedSize只要是希望UI界面盡可能和屏幕分辨率適配,如移動設備上,特別是手機上,屏幕就那么小,UI界面一定要求全屏顯示,就要進行縮放。

 

       對于Unity實際開發中屏幕自適應問題,oneRain在①中有更詳細的描述,這里只介紹下,D.S.Qiu想到的一種自適應策略——“花草”填充法。填充法(這個是D.S.Qiu命名的,哈哈,自戀下)指的是用其他圖片區填充因為固定比例放縮而出現鏤空黑邊的區域,當然也可能已經有游戲是這么做的,當然oneRain說的增加一個寬度縮放比例,長寬分別以盡可能接近屏幕長寬比的比例去縮放。

 

Scale的實現

       雖然我們已經了解了Scale的作用區別以及策略,那到底是怎么實現的呢?還是上代碼:

C#代碼  收藏代碼void Update ()      {          if (mTrans != null)          {              float calcActiveHeight = activeHeight;              if (calcActiveHeight > 0f )              {                  float size = 2f / calcActiveHeight;                  Vector3 ls = mTrans.localScale;                        if (!(Mathf.Abs(ls.x - size) <= float.Epsilon) ||                      !(Mathf.Abs(ls.y - size) <= float.Epsilon) ||                      !(Mathf.Abs(ls.z - size) <= float.Epsilon))                  {                      mTrans.localScale = new Vector3(size, size, size);                  }              }          }      }  

       可以看出Update函數中是根據activeHeight來調整UIRoot的transform的localScale來實現的,哈,竟可以這么簡單。那么,我們只要弄清楚activeHeight就可以了:

C#代碼  收藏代碼public int activeHeight      {          get          {              int height = Mathf.Max(2, Screen.height);              if (scalingStyle == Scaling.FixedSize) return manualHeight;   #if UNITY_ipHONE || UNITY_ANDROID              if (scalingStyle == Scaling.FixedSizeOnMobiles)                  return manualHeight;  #endif              if (height < minimumHeight) return minimumHeight;              if (height > maximumHeight) return maximumHeight;              return height;          }      }  

       可以看出activeHeight就是前面Scale Style的不同參數的具體實現,即得到縮放參考高度。

 

Orthographic Size和分辨率

       

       在上面Update和activeHeight的函數中都出現了  “2” 這個常數,這個常數到底是怎么來的。要想知道這個,就要明白Camera 設定為Orthographic類型中的Size(即Orthographic Size)的含義,查看Unity文檔,就可以知道這個Size是Camera看到區域的一半,如果Size設置為1,則Camera可以看到高度為為2的區域,然后我們知道照相機看到的區域是全畫在整個屏幕的,也就是說Size的值對應為屏幕分辨率的一半。

        如果屏幕寬度為1000個像素,Size設置的值表示1000/2=500個像素。所以,我們通過整個關系計算UIRoot下的GameObject的實際對應屏幕的高度:從GameObject向上一直到UIRoot,將它們的loaclScal相乘得到的乘積除以Size乘以屏幕高度的一半,即(localScale*....localScale)/Size*Screen.height/2。

        這可以解釋UIRoot的localStyle為啥都是很小的小數,因為這樣可以保證UIRoot的子節點都可以以原來的大小作為localScale,比如一張圖片是20*20的,我們可以直接設置localScale為(20,20,1)不用進行換算,直觀方便。(NGUI3.0(or 2.7)以后的版本已經不再使用localScale來表示UISPRite ,UILable(UIWidget的子類)的大小了,而是在UIWidget的width和height來設置,這樣做的好處就是一個gameObject節點可以掛多個UISprite或UILabel了,而不會受localScale的沖突影響    2013/11/16增補)。

 

 

UIRoot細節

      前面說道Update函數中有一個常數 2 ,表示Size是設置為1的,這個可以從Start函數就可以知道:

C#代碼  收藏代碼protected virtual void Start ()      {          UIOrthoCamera oc = GetComponentInChildren<UIOrthoCamera>();          if (oc != null)          {              Debug.LogWarning("UIRoot should not be active at the same time as UIOrthoCamera. Disabling UIOrthoCamera.", oc);              Camera cam = oc.gameObject.GetComponent<Camera>();              oc.enabled = false;              if (cam != null) cam.orthographicSize = 1f;          }          else Update();      }  

      但是這里似乎有點疏忽,這里只移除UIOrthoCamera這個腳本(UIRoot腳本開始就言明這兩個腳本不能同時使用,所以要移除),并將cam的orthographicSize設置為1f,但是我想如果沒有UIorthoCamera這個腳本的話,就不會重新設置Camera的orthographicSize值,這樣如果orthographicSize不是1的話,效果就不一樣了。剛開始我會以為這是NGUI developer的一個Bug,但是如果都在Start設置orthographicSize為1f,那這個參數就沒有意義了,讓使用者自己設置可以有更多效果,如“屏中屏”——將滿屏的UI縮放為另外一個UI界面的一半大小,所以才會說“似乎有點疏忽”。

      下面看下效果圖:

  orthographicSize=1  orthographicSize=2

        很明顯可以orthographicSize=2時,圖片進行了縮小。當orthographicSize=1時背景圖片用了UIStretch腳本來實現滿屏效果,當orthographicSize為2時卻沒有滿屏,這就說明代碼中UIRoot是以2為屏幕寬度的,現在Camera的視野大小為4,那映射到屏幕當然不會有“滿屏”的效果了(只會是屏幕寬度的一半),背景圖片在左上角是因為使用UIAnchor腳本。

         ②和③中分別都介紹了如何設置Orthographic Size來達到像素和Unity中單位對應起來,都寫的很不錯,這也是我寫這篇博客的一個觸動。

     

         UIRoot中還有兩類函數:GetPixelSizeAdjustment 和 Broadcast,前者是獲取當前分辨率的單個像素的大小,而后者其實就一個UIRoot的消息廣播函數,還有一個當前激活狀態下的UIRoot的隊列。至此D.S.Qiu已經將UIRoot腳本解析的淋漓盡致了,自然就剩下小結了。

 

基于寬度放縮

       

        UIRoot是基于高度放縮的,即放縮的比例是以高度為參考的,所以UIRoot有一個manualHeight的參數。那么對于橫版游戲顯然不行,要是能實現基于寬度放縮。所以可以通過設置一個“manualWidth”的參數來做。比如我們項目中使用的是 1024 作為UI的寬屏尺寸,通過換算設置manualHeight的值:

 

C#代碼  收藏代碼int height = Mathf.Max(2, Screen.height);  manualHeight = Screen.height * 1024 / Screen.width; //基于寬度的屏幕分辨率自適應  

        之前的同事用了很多方法都沒有搞定,其實根本就沒有那么復雜,所以一旦知道原理之后,很多事情就變得簡單多了。

                                                                                                                     增補于  2013,12,23             22:14

小結:

        一直都想把NGUI的內部機制徹底的弄明白,一直都沒付諸實踐,知道看②和③中的文章,D.S.Qiu發現還是有必要盡快整理下,切好最近項目沒什么事情,也是周末。UIRoot這個腳本雖然很簡單,但確實NGUI整個體系的基石。更多NGUI文章點擊查看。

 

        如果您對D.S.Qiu有任何建議或意見可以在文章后面評論,或者發郵件(gd.s.qiu@Gmail.com)交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。

 

        轉載請在文首注明出處:http://dsqiu.iteye.com/blog/1964679

更多精彩請關注D.S.Qiu的博客和微博(ID:靜水逐風)

        

        

 

 

       

        

 

 

參考:

①oneRain: http://blog.csdn.net/onerain88/article/details/11713299

②風宇沖: http://blog.sina.com.cn/s/blog_471132920101fua3.html

③midashao:http://blog.csdn.net/midashao/article/details/8232341


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 枝江市| 筠连县| 弥渡县| 嘉黎县| 灵寿县| 大竹县| 彩票| 乌拉特前旗| 阿城市| 瑞金市| 上高县| 绍兴市| 巩义市| 彭州市| 镇雄县| 建水县| 福贡县| 灌南县| 高州市| 仲巴县| 资中县| 普格县| 赤水市| 威海市| 徐州市| 彭泽县| 镇江市| 清新县| 郴州市| 武邑县| 沙湾县| 化德县| 莱芜市| 元氏县| 玉溪市| 茶陵县| 阳曲县| 富宁县| 琼中| 义马市| 靖江市|