NGUI如何进行自适应UI重叠问题解决方案

NGUI如何进行自适应
NGUI本身按照高度适配的原则进行适配。
首先分析一下UIROOT,因为所有NGUI下的面板默认在UIROOT树下。

一、分析UIROOT的ScalingStyle = Flexible的情况下自适应的问题,该方式保持原像素,不进行缩放。分辨率的变化不影响UI的像素。

在Unity Editor下按照UIRoot Minimum Height设定高度来显示页面,当页面在目标设备上显示时,NGUI会根据目标设备的高度来调节UIROOT节点的scale,整个页面适应目标的高度,例如当前设备的高度为1024,那么页面的实际显示高度会在min和max之间取的一个值去设置scale缩放适应当前设备,当目标设备宽高刚好和页面宽高比一致时,页面就完美在设备上显示了。
但是问题来了:

1.当目标设备的宽高比小于页面宽高比时(400/800,800/1280),页面高度适配后,宽度将大于设备宽度,是的页面横向多出的部分无法显示,反之,页面横向将不足于填充设备。
2.还有一个重要的是NGUI自带的UIAnchor锚点,将整个界面分成了九个区域,TopLeft/Top/TopRight/Left/Center/Right/BottomLeft/Bottom/BottomRight
UIAnchor组件的节点都会自动参照各个区域进行停靠,如此,对于第一个问题来说,页面填充问题似乎是解决了,但是经过实践,会出现问题是,页面左右边距在设备宽高比小于页面宽高比时变小,便出现UI重叠现象,当然,如果设备宽高比大于页面宽高的话,页面左右边距变大,UI不会出现重叠。

问题综述:
1.当目标设备宽高比小于页面宽高比时,UI出现重叠,类似全屏BG(sprite)被裁剪。
2.当目标设备宽高比大于页面宽高比时,类似全屏的BG(sprite)将不能铺满整个屏幕。

补充:
1000/500 大于 1280/720,按照宽高比来说貌似是不用考虑重叠问题,但是因为1000小于1280,还是会出现UI重叠问题,已实践证明。所以,以下方法,不采用宽高比,而是采用实际宽高。

解决问题
定义几个常量
panel_width        页面固定宽度
panel_height       页面固定高度
device_width        目标设备宽度
device_height        目标设备高度

重叠问题:
    当device_height小于panel_height时,UIROOT会根据device_height调整scale大小来适应高度,如此,宽度的缩放便不足于显示整个页面,那么我们可以考虑改变2d相机的Orthographic模式下的Size来调整相机,以便于能够完全照射足够宽度的页面。

如此,便使得整个页面都可以显示,因为,UIAnchor的存在,UI左右的距离将通过改变相机的方式而保持不变,上下间距则会适应设备进行相应的变大。
代码:
[mw_shl_code=csharp,true]using UnityEngine;
using System.Collections;
[RequireComponent(typeof(UICamera))]
public class CameraAspect : MonoBehaviour
{
    ///
    /// 根据设备的宽高比,调整UICamera.OrthographicSize. 以保证UI在不同分辨率(宽高比)下的自适应
    /// 须与UIAnchor配合使用
    /// 将该脚本添加到UICamera同一节点上
    ///

    float panel_width = 1280f;
    float panel_height = 720f;
    float device_width = 0f;
    float device_height = 0f;
    void Awake()
    {
        device_width = Screen.width;
        device_height = Screen.height;
        SetCameraSize();
    }
    void Update()
    {
        if (device_width != Screen.width || device_height != Screen.height)
        {
            device_width = Screen.width;
            device_height = Screen.height;
            SetCameraSize();
        }
    }
    private void SetCameraSize()
    {
        float width_aspect = 0;
        float height_aspect = 0;
        if (device_width < panel_width)
        {
            width_aspect = panel_width / device_width;
        }
        if (device_height < panel_height)
        {
            height_aspect = panel_height / device_height;
        }
        if (width_aspect > height_aspect)
        {
            camera.orthographicSize = width_aspect;
        }
        else if (width_aspect < height_aspect)
        {
            camera.orthographicSize = height_aspect;
        }
    }
}[/mw_shl_code]
总之,在使用该方法后,如果设备的宽度小于页面宽度或者设备高度小于页面高度(可能有纵向UI重叠问题),求出宽和高的比率,然后选择最适宜的比率去改变相机size.

测试分辨率(默认编辑初始1280 * 720 = 8 : 5)
640 * 480 
绑定CameraAspect 脚本测试

未出现重叠。

不绑定CameraAspect 脚本测试

出现重叠。

1000 *  500
绑定CameraAspect 脚本测试



不绑定CameraAspect脚本测试

出现重叠

总结:代码测试成功,但是也产生了一个问题就是,因为相机的size是固定比率缩放,所以在某些sprite会出现宽或者高不足的情况,因为当前是在像素上的模式,不会自动跟随UIROOT进行缩放。

以上针对重叠问题适用于PC和移动端。

类似全屏的BG(sprite)将不能铺满整个屏幕或者被裁剪方法:
如果是个人电脑:
完全可以预备当前各种主流显示器分辨率的图。(⊙o⊙)…好吧。
其实,PC端的图都比较高,来点缩放什么的,不会影响什么的。


如果是手机:
解决方法是放大sprite scale:
  sprite.transform.localScale * = height_aspect
        或者
       sprite.transform.localScale * = weight_aspect
        这样会使得sprite在横向或者纵向上被裁切,宽高比不同必然的结果... 当然也可以选择只调整高度或宽度,只要能接受变形...
代码自行脑补。

其他2个方式,UIRoot下会自行根据当前分辨率进行缩放,所以只需要采用anchor方式就行,不用考虑重叠问题。

如果对意向sprite铺满或者裁剪问题有更好的处理方法,求指导。O(∩_∩)O~

转载请注明出处。

作者: 大帅纷纭

微博:http://weibo.com/2357191704/profile?topnav=1&wvr=6

博客:http://blog.csdn.net/dashuaifenyun1991

邮箱:[email protected]


你可能感兴趣的:(Unity3D,C#)