zoukankan      html  css  js  c++  java
  • 【原】NGUI中的UIAnchor脚本功能

    UIAnchor的功能是把对象锚定在屏幕的边缘(左上,左中,左下,上,中,下,右上,右中,右下),或缩放物体使其匹配屏幕的尺寸。

    在1.90版本后,拉长(缩放)的功能被放到UIStretch中,UIAnchor的功能更单一了,就是给对象定位。

    借用《【Unity插件】NGUI核心组件之UIAnchor》文章中的内容:

    NGUI:UIAnchor

    Anchor脚本可以用来实现多个目的,这些在Example0里面都有用到。

    1. 只要提供一个half-pixel偏移量,它可以让一个控件的位置在Windows系统上精确的显示出来(只有这个Anchor的子控件会受到影响)

    2. 如果挂载到一个对象上,那么他可以将这个对象依附到屏幕的角落或者边缘

    参数

    UI Camera 是渲染这些对象的摄像机,如果没有手动设置,它会自动设置一个场景中的摄像机

    Side 设置锚点,分别可以设置4个角,4个边和中心点

    Half Pixel Offset 可以让对象在windows系统上显示的时候,有半个像素的偏移量。2D UI界面需要勾选上这个

    Depth Offset 用来调整UIAnchor计算出来的位置的深度。它主要作用于基于透视的摄像机。这个值是世界坐标,与摄像机的远近裁切面类似

    Relative Offset 相对偏移量 让你可以为物体设置以屏幕半分比为单位的偏移量

    Tips

    1. 如果一个对象上面挂载了一个UIAnchor,那么他的transform的值不能被手动修改-他们是被脚本控制的。如果你想对锚点加一个偏移量,那么给他添加一个子物体。举例来说,为了保证你的控件在一直在(100,100)的位置,你的对象结构应该是:UI->Anchor->Offset->Widget。

    2. 如果你想将一个控件的位置设置为屏幕左边25%的位置,你可以将他设置为一个UIAnchor的子物体,这个UIAnchor的Side设置为Left,Relateive Offset 的X值设置为0.25。

    脚本运行的前提是在UIRoot中能找到Camera对象,如果找不到就不会有任何效果。

    定位只考虑屏幕的尺寸,并不考虑节点下的对象尺寸。默认情况下,UIAnchor附着在一个空的GameObject,脚本获得Camera的pixelRect属性(相机被渲染到屏幕像素中的位置),通过如下代码定位到屏幕边缘的8个像素点和1个中心像素点上。

     1             Rect rect = uiCamera.pixelRect;
     2             float cx = (rect.xMin + rect.xMax) * 0.5f;
     3             float cy = (rect.yMin + rect.yMax) * 0.5f;
     4             Vector3 v = new Vector3(cx, cy, depthOffset);
     5 
     6             if (side != Side.Center)
     7             {
     8                 if (side == Side.Right || side == Side.TopRight || side == Side.BottomRight)
     9                 {
    10                     v.x = rect.xMax;
    11                 }
    12                 else if (side == Side.Top || side == Side.Center || side == Side.Bottom)
    13                 {
    14                     v.x = cx;
    15                 }
    16                 else
    17                 {
    18                     v.x = rect.xMin;
    19                 }
    20 
    21                 if (side == Side.Top || side == Side.TopRight || side == Side.TopLeft)
    22                 {
    23                     v.y = rect.yMax;
    24                 }
    25                 else if (side == Side.Left || side == Side.Center || side == Side.Right)
    26                 {
    27                     v.y = cy;
    28                 }
    29                 else
    30                 {
    31                     v.y = rect.yMin;
    32                 }
    33             }

    所以,如果在UIAnchor下的Panel中创建一个Button,默认情况把UIAnchor定位到左下,Button只会奇怪的露出1/4。因为Button的中心随着UIAnchor被定位在屏幕的左下角的像素上了。

    另一个有用的参数是relativeOffset,这是个百分比参数。屏幕的宽和高被乘以偏移百分比后,加到记录屏幕中点的变量上,用有效的Camera转为对应的世界度坐标,并重新给UIAnchor来定位:

     1             float screenWidth  = rect.width;
     2             float screenHeight = rect.height;
     3 
     4             v.x += relativeOffset.x * screenWidth;
     5             v.y += relativeOffset.y * screenHeight;
     6 
     7             if (uiCamera.orthographic)
     8             {
     9                 v.x = Mathf.RoundToInt(v.x);
    10                 v.y = Mathf.RoundToInt(v.y);
    11 
    12                 if (halfPixelOffset && mIsWindows)
    13                 {
    14                     v.x -= 0.5f;
    15                     v.y += 0.5f;
    16                 }
    17             }
    18 
    19             // Convert from screen to world coordinates, since the two may not match (UIRoot set to manual size)
    20             v = uiCamera.ScreenToWorldPoint(v);
    21 
    22             // Wrapped in an 'if' so the scene doesn't get marked as 'edited' every frame
    23             if (mTrans.position != v) mTrans.position = v;

    UIAnchor的完整代码:

    //----------------------------------------------
    //            NGUI: Next-Gen UI kit
    // Copyright © 2011-2012 Tasharen Entertainment
    //----------------------------------------------
    
    using UnityEngine;
    
    /// <summary>
    /// This script can be used to anchor an object to the side of the screen,
    /// or scale an object to always match the dimensions of the screen.
    /// </summary>
    
    [ExecuteInEditMode]
    [AddComponentMenu("NGUI/UI/Anchor")]
    public class UIAnchor : MonoBehaviour
    {
        public enum Side
        {
            BottomLeft,
            Left,
            TopLeft,
            Top,
            TopRight,
            Right,
            BottomRight,
            Bottom,
            Center,
        }
    
        public Camera uiCamera = null;
        public Side side = Side.Center;
        public bool halfPixelOffset = true;
        public float depthOffset = 0f;
        public Vector2 relativeOffset = Vector2.zero;
    
        // Stretching is now done by a separate script -- UIStretch, as of version 1.90.
        [HideInInspector][SerializeField] bool stretchToFill = false;
    
        Transform mTrans;
        bool mIsWindows = false;
    
        /// <summary>
        /// Legacy support.
        /// </summary>
    
        void Start ()
        {
            if (stretchToFill)
            {
                stretchToFill = false;
    
                UIStretch stretch = gameObject.AddComponent<UIStretch>();
                stretch.style = UIStretch.Style.Both;
                stretch.uiCamera = uiCamera;
            }
        }
    
        /// <summary>
        /// Automatically find the camera responsible for drawing the widgets under this object.
        /// </summary>
    
        void OnEnable ()
        {
            mTrans = transform;
    
            mIsWindows = (Application.platform == RuntimePlatform.WindowsPlayer ||
                Application.platform == RuntimePlatform.WindowsWebPlayer ||
                Application.platform == RuntimePlatform.WindowsEditor);
    
            if (uiCamera == null) uiCamera = NGUITools.FindCameraForLayer(gameObject.layer);
        }
    
        /// <summary>
        /// Anchor the object to the appropriate point.
        /// </summary>
    
        void Update ()
        {
            if (uiCamera != null)
            {
                Rect rect = uiCamera.pixelRect;
                float cx = (rect.xMin + rect.xMax) * 0.5f;
                float cy = (rect.yMin + rect.yMax) * 0.5f;
                Vector3 v = new Vector3(cx, cy, depthOffset);
    
                if (side != Side.Center)
                {
                    if (side == Side.Right || side == Side.TopRight || side == Side.BottomRight)
                    {
                        v.x = rect.xMax;
                    }
                    else if (side == Side.Top || side == Side.Center || side == Side.Bottom)
                    {
                        v.x = cx;
                    }
                    else
                    {
                        v.x = rect.xMin;
                    }
    
                    if (side == Side.Top || side == Side.TopRight || side == Side.TopLeft)
                    {
                        v.y = rect.yMax;
                    }
                    else if (side == Side.Left || side == Side.Center || side == Side.Right)
                    {
                        v.y = cy;
                    }
                    else
                    {
                        v.y = rect.yMin;
                    }
                }
    
                float screenWidth  = rect.width;
                float screenHeight = rect.height;
    
                v.x += relativeOffset.x * screenWidth;
                v.y += relativeOffset.y * screenHeight;
    
                if (uiCamera.orthographic)
                {
                    v.x = Mathf.RoundToInt(v.x);
                    v.y = Mathf.RoundToInt(v.y);
    
                    if (halfPixelOffset && mIsWindows)
                    {
                        v.x -= 0.5f;
                        v.y += 0.5f;
                    }
                }
    
                // Convert from screen to world coordinates, since the two may not match (UIRoot set to manual size)
                v = uiCamera.ScreenToWorldPoint(v);
    
                // Wrapped in an 'if' so the scene doesn't get marked as 'edited' every frame
                if (mTrans.position != v) mTrans.position = v;
            }
        }
    }
    View Code

    原文地址:http://www.cnblogs.com/basecn/p/NGUI_UIAnchor.html 

  • 相关阅读:
    转载 | float 清除浮动的7种方法
    转载 | CSS图片下面产生间隙的 6种解决方案
    (转载)内联元素设置宽高问题
    HTML/CSS:display:flex 布局教程
    HTML/CSS:block,inline和inline-block概念和区别
    上传文件
    分页查询 模糊查询 合体查询
    repeater的command用法
    窗体内的控制 跨窗体控制
    webform 跨窗体传值
  • 原文地址:https://www.cnblogs.com/basecn/p/NGUI_UIAnchor.html
Copyright © 2011-2022 走看看