文章出處

一、當下移動設備的主流分辨率(數據來自“騰訊分析移動設備屏幕分辨率分析報告”)
1.1 iOS設備的分辨率主要有:
 
寬  寬高比
960 640 1.5
1136 640 1.775
1024 768 1.3333
2048 1536 1.3333
 
Android設備的分辨率則相對紛雜,主流的分辨率有:
寬高比
800 480 1.6667
854 480 1.7792
1280 720 1.7778
960 540 1.7778
1280 800 1.6
960 640 1.5
1184 720 1.6444
1920 1080 1.7778


二、NGUI默認的多分辨率適配原則
NGUI本身按照“高度適配”的原則進行多分辨率下的UI適配,其默認的高度通過 UIRoot.manualHeight 設置。再配合使用 UIAnchor 便可實現一定程度的多分辨率適配。
 
其中,在Unity Editor下按照 UIRoot.manualHeight 設定的高度,編輯UI頁面。這樣,當UI頁面在目標設備上顯示時,NGUI按照目標設備的高度(targetHeight)來調整UIRoot節點的scale,以使整個UI頁面適應目標設備的高度。比如manualHeight=400,而targetHeight=800,那么UIRoot的scale將被乘以2。所以,當目標設備的寬高比與所編輯頁面的寬高比一致時,整個UI將完美顯示;當目標設備寬高比小于所編輯的寬高比時,頁面寬度將大于設備寬度,使得多出的部分無法顯示;而當目標設備寬高比大于所編輯寬高比時,頁面寬度小于設備寬度,設備兩邊將出現黑邊。
 
而UIAnchor則是將整個頁面分為TopLeft/Top/TopRight/Left/Center/Right/BottomLeft/Bottom/BottomRight九個區域,掛載了UIAnchor組件的節點都將按照設置自動停靠到相應的區域中。有了UIAnchor,上面的兩個問題將被一定程度的解決:當目標設備寬高比小于編輯的寬高比時,由于UIAnchor的自動停靠功能,UI不會被裁切掉,但UI之間的左右間距將相應變小,便有可能出現UI重疊的問題;當目標設備寬高比大于所編輯寬高比時,UI之間的左右間距將變大,好在這樣起碼不會有UI被裁切或重疊。
 
看似我們只需要解決UI重疊的問題就搞定了。不過讓我們再仔細想一下,一張鋪滿整個屏幕的UISprite不管是否使用UIAnchor,在目標設備寬高比更小時,sprite都會在橫向上被裁切,而將目標設備寬高比更大時,sprite都不能鋪滿整個屏幕。
 
問題出來了:
1. 當目標設備寬高比更小時的UI重疊問題
2. 當目標設備寬高比更小時,全屏sprite被裁切問題
3. 當目標設備寬高比更大時,全屏sprite不能鋪滿整個屏幕的問題
 
 
三、解決問題
首先定義幾個變量:
standard_width  編輯頁面的原始寬度
standard_height  編輯頁面的原始高度
device_width    目標設備的寬度
device_height    目標設備的高度
standard_aspect  編輯頁面的寬高比
device_aspect    目標設備的寬高比
 
1. 目標設備寬高比更小時的UI重疊問題
  當device_aspect小于standard_aspect時,UIRoot根據device_height調整其scale大小,因而使得設備寬度不足以顯示整個頁面。我們調整Camera.orthographicSize(僅適用2D GUI),以足夠顯示頁面的寬度。令
  Camera.orthographicSize = standard_aspect / device_aspect;
即,改變了NGUI原有的“高度適配”原則,轉為“寬度適配”,使得整個頁面都得以顯示,而由于UIAnchor的存在,UI的左右間距保持不變,但上下間距會變大。
該方法可以實現為一個MonoBehaviour腳本(UICameraAdjustor.cs),掛載到UICamera同一個節點上,代碼如下:
 
復制代碼
 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 /// <summary>
 5 /// 根據設備的寬高比,調整camera.orthographicSize. 以保證UI在不同分辨率(寬高比)下的自適應
 6 /// 須與UIAnchor配合使用
 7 /// 將該腳本添加到UICamera同一節點上
 8 /// </summary>
 9 
10 [RequireComponent(typeof(UICamera))]
11 public class UICameraAdjustor : MonoBehaviour
12 {
13     float standard_width = 1024f;
14     float standard_height = 600f;
15     float device_width = 0f;
16     float device_height = 0f;
17 
18     void Awake()
19     {
20         device_width = Screen.width;
21         device_height = Screen.height;
22 
23         SetCameraSize();
24     }
25 
26     private void SetCameraSize()
27     {
28         float adjustor = 0f;
29         float standard_aspect = standard_width / standard_height;
30         float device_aspect = device_width / device_height;
31 
32         if (device_aspect < standard_aspect)
33         {
34             adjustor = standard_aspect / device_aspect;
35             camera.orthographicSize = adjustor;
36         }
37     }
38 }
復制代碼

 

總之,在使用該方法后,當device_aspect大于standard_aspect時,UI按照高度適配原則,UI的上下間距不變,左右間距變大;當device_aspect小于standard_aspect時,UI按照寬度適配原則,UI的左右間距不變,上下間距變大。
 
2. 目標設備寬高比更小時,全屏sprite被裁切問題
  全屏背景的sprite被裁切可能在很多情況下不會成為什么問題,但在我們使用了解決問題1中的方法后,這里的“被裁切問題”就變為了同問題3類似的“不能鋪滿整個屏幕問題”。解決方法是放大sprite scale:
  sprite.transform.localScale *= ( standard_aspect / device_aspect );
這樣會使得sprite在橫向上被裁切,寬高比不同必然的結果... 當然也可以選擇只調整高度或寬度,只要能接受變形...
 
3. 目標設備寬高比更大時,全屏sprite不能鋪滿整個屏幕的問題
   同問題2,解決方法同樣是放大sprite scale:
  sprite.transform.localScale *= ( device_aspect / standard_aspect );
這樣會使得sprite在縱向上被裁切。
 
問題2和3的解決方法相應腳本(UIBackgroundAjustor.cs)會在文章后面給出。
該腳本須掛載到sprite同一節點上,配合UIAnchor使用,可以選擇是裁切方向。如UIAnchor停靠方式使用center,則sprite會被左右兩邊或上下裁切,若使用Top,則會左右裁切或下邊裁切。
總之,全屏sprite會始終鋪滿整個屏幕,不會出現黑邊。當device_aspect大于standard_aspect時,全屏sprite按照寬度適配,縱向裁切;當device_aspect小于standard_aspect時,按照高度適配,橫向裁切。
 
四、優化
1. UI頁面的制作尺寸按 1024 X 600
  前面講到主流分辨率的情況,其平均寬高比(除ipad2/3/4以外)大概為1.7,與主流的寬高比都不會偏差很大。即,在使用上面的多分辨率解決方法時,UI不會在縱向或橫向上的間距過大,顯得特別離譜。按照此寬高比,我們選擇1024x600的尺寸來制作UI,并嚴格要求UI制作時,頁面分為TopLeft/Top/TopRight/Left/Center/Right/BottomLeft/Bottom/BottomRight九個區域,以便掛載UIAnchor。
 
2. 全屏背景的制作按 1024 X 768
  如果全屏背景圖也按1024 x 600制作,在ipad2/3/4上就會有較大程度的放大。同時考慮到NGUI的打包atlas,使用2的冪次尺寸,高度600和768都將占用1024x1024的atlas。所以全屏背景在制作時,高度上做出一定的冗余尺寸,以使寬高比小于1.7時,高度上放大系數不會太大,避免圖片嚴重失真。
  加入冗余尺寸后的腳本(UIBackgroundAjustor.cs)如下:
復制代碼
 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 /// <summary>
 5 /// 根據設備的寬高比,調整UISprite scale, 以保證全屏的背景圖在不同分辨率(寬高比)下的自適應
 6 /// 將該腳本添加到UISprite同一節點上
 7 /// 須與UICameraAdjustor腳本配合使用
 8 /// </summary>
 9 
10 [RequireComponent(typeof(UISprite))]
11 public class UIBackgroundAdjustor : MonoBehaviour
12 {
13     float standard_width = 1024f;
14     float standard_height = 600f;
15     float device_width = 0f;
16     float device_height = 0f;
17 
18     void Awake()
19     {
20         device_width = Screen.width;
21         device_height = Screen.height;
22 
23         SetBackgroundSize();
24     }
25 
26     private void SetBackgroundSize()
27     {
28         UISprite m_back_sprite = GetComponent<UISprite>();
29 
30         if (m_back_sprite != null && UISprite.Type.Simple == m_back_sprite.type)
31         {
32             m_back_sprite.MakePixelPerfect();
33             float back_width = m_back_sprite.transform.localScale.x;
34             float back_height = m_back_sprite.transform.localScale.y;
35 
36             float standard_aspect = standard_width / standard_height;
37             float device_aspect = device_width / device_height;
38             float extend_aspect = 0f;
39             float scale = 0f;
40 
41             if (device_aspect > standard_aspect) //按寬度適配
42             {
43                 scale = device_aspect / standard_aspect;
44 
45                 extend_aspect = back_width / standard_width;
46             }
47             else //按高度適配
48             {
49                 scale = standard_aspect / device_aspect;
50 
51                 extend_aspect = back_height / standard_height;
52             }
53 
54             if (extend_aspect >= scale) //冗余尺寸足以適配,無須放大
55             {
56             }
57             else //冗余尺寸不足以適配,在此基礎上放大
58             {
59                 scale /= extend_aspect;
60                 m_back_sprite.transform.localScale *= scale;
61             }
62         }
63     }
64 }

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()