UNITY3D使用NGUI制作自适应UI的总结

原地址:http://www.cnitblog.com/updraft/archive/2013/11/12/88801.html

制作自适应的几个方法
1. 使用 UIROOT 里设置自定义高度的方法,然后配合 ANCHOR 左对齐,右对齐等方式,但在手机上经常会遇到宽高比不一样的分辨率,最后结果就是没有右对齐的部分容易被剪切。
    优势:简单,不用额外写脚本了,而且匹配的精度是原始的,效果也不错
    缺点:遇到宽高比不一致就没法解决了,有些UI会被剪切,而且居中TILED的部分在类似IPAD中正确,但在iphone会变得很大。

2. 使用UIStretch拉伸anchor或者uipanel,这种方法不算完美的自适应ui,纯粹只是按比例缩放拉伸对象和窗口,不过可以适配所有宽高比,而且整体UI的比例能保持不变。
    优势:简单,不用写额外的脚本,适合所有宽高比
    缺点:纯粹是拉伸对象,在宽高比差异很大时,整个UI变形比较大。而且还有个最大的问题,在使用UIPANEL的剪切(CLIPPING)功能时,UIStretch会导致剪切失效,所以使用clipping时是无法使用uistretch的。

3. 方法同2一样,使用UIStretch,但需要增加脚本处理下UIPanel,让uipanel的clipping能正常工作。
    通过查看uipanel的clipping的源码可以发现剪切是必须要求x,y,z的scale值一模一样的,但实际上一模一样也不能保证正确的clipping,我尝试改成(2,2,2)这种,剪切范围是对了,但UIPANEL不允许移动,一旦移动就会导致剪切范围移动,这个尼玛太不科学了。。。 特别是 UIDraggablePanel 使用了剪切后,直接拖出屏幕外边了。
    所以UIPANEL的scale值在全局范围内只能是(1,1,1),不是localScale=(1,1,1),所以需要取得uipanel对应的anchor上的uistretch修改的scale值,然后做一个逆变换,让其全局scale变为(1,1,1),在panel下动态创建一个group对象,把panel之前的所有孩子节点移动上去,重新增加一个uistretch,让uipanel保持1,1,1的比例,其他对象保持stretch的比例就ok了。

代码示例如下:

//  clipping panel auto uniform & change clipping range
public class EF_C_NGUI_Clipping_Panel_Uniform : MonoBehaviour
{
    public Transform ParentAnchor           = null;
    private bool m_IsInit                   = false;

    void Update()
    {
        if( m_IsInit == false )
        {
            m_IsInit                        = true;
            this.enabled                  = false;

            //  make uniform
            MakeUniform();
        }
    }

    //  make uniform
    void MakeUniform()
    {
        if( ParentAnchor == null )
            return;

        //  create parent obj
        GameObject objParent                = new GameObject("Panel_Clipping_Parent");
        GameObject objParent_Root           = new GameObject("Panel_Clipping_Parent_ROOT");
        Transform parentObj                 = objParent.transform;
        Transform parentObj_Root            = objParent_Root.transform;
        if( parentObj == null )
            return;

        //  root parent
        {
            parentObj_Root.parent           = transform;
            parentObj_Root.localPosition    = Vector3.zero;
            parentObj_Root.localRotation    = Quaternion.identity;
            parentObj_Root.localScale       = new Vector3(1,1,1);

            parentObj_Root.parent           = transform.parent;
        }

        //  set parent obj data
        {
            //  parentObj.parent                    = transform;
            parentObj.parent                = parentObj_Root;
            parentObj.localPosition         = Vector3.zero;
            parentObj.localRotation         = Quaternion.identity;
            parentObj.localScale            = new Vector3(1,1,1);
        }

        //  change panel parent
        transform.parent                    = parentObj;

        //  get scale
        Vector3 parentScale                 = ParentAnchor.localScale;
        Vector3 objScale                    = parentObj.transform.localScale;

        //  change clip range for current screen
        UIPanel panelObj                    = gameObject.GetComponent<UIPanel>();
        if( panelObj != null )
        {
            Vector4 oldClipRange            = panelObj.clipRange;
            panelObj.clipRange              = new Vector4( oldClipRange.x, oldClipRange.y
                                                         , oldClipRange.z * ( parentScale.x / objScale.x )
                                                         , oldClipRange.w * ( parentScale.y / objScale.y ) );
        }

        //  make uniform
        objScale.x                          = 1.0f / parentScale.x;
        objScale.y                          = 1.0f / parentScale.y;
        objScale.z                          = 1.0f / parentScale.z;

        parentObj.transform.localScale      = objScale;
    }
}

posted @ 2014-08-11 07:42  ing...  阅读(1834)  评论(1编辑  收藏  举报