当你开始使用NGUI的时候,简单的从项目视图 中一个”Control”预设体 拖拽到场景视图中,你将会发现 Hierarchy层次面板中会出现以下层次结构:

  1. 其中 UI Root作为根节点,是每个NGUI元素的顶级父节点
  2. 在Unity中,每个元素都具有最基本的Transform属性,这也叫基元属性;
  3. UI Root是用于管理和处理UI的变化和缩放
  4. Camera其实是一个独立的UICamera,负责渲染UI对象到视图中,作为UI Root的子节点存在
  5. 剩下的蓝色文字的物体就是最关键的UI部分.

(一) UI Root缩放方式之 Scaling Style

    1. NGUI中 UI Root 缩放方式有三种,默认为Flexible

      public enum Scaling
          {
              Flexible,
              Constrained,
              ConstrainedOnMobiles,
          }

public Scaling scalingStyle = Scaling.Flexible;

Flexible style lets your UI always be in pixels, and a 300x200 widget will always take 300 by 200 pixels on the screen. This also means that viewing your UI on a low-res device will make your widgets appear rather large in size, and viewing your UI on a high-res device will make your widgets appear small. On the plus side, with this setting your UI will always remain as crisp as possible.

译:Flexible style 灵活的方式让你操作UI.比如你设置300*200 px的UI Root Fiexible,那么你的UI 元素将永远保持在300 * 200 像素,并且不会进行任何缩放.也就是说在低分辨率的设备下你的UI画面中的元素将会显得非常大,而在高分辨率的设备中,你的UI画面元素将会变得非常小. 唯一的好处就是这个UI将会保持这个分辨率,不会随着画面和设备而改变.当选择这个选项的时候,不要忘记手动设置高度.

public Scaling activeScaling
{
get
{
Scaling scaling = scalingStyle; if (scaling == Scaling.ConstrainedOnMobiles)
#if UNITY_EDITOR || UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_WP_8_1 || UNITY_BLACKBERRY
return Scaling.Constrained;
#else
return Scaling.Flexible;
#endif
return scaling;
}
}

他们之间的关系是:默认为Flexible,若手动选 Scaling.ConstrainedOnMobiles,应该符合的平台是编辑器,IPhone,安卓,Window Phone8或者Unity_WP_8_1,或者黑莓.那么这些情况将把UI Root缩放方式变为Scaling.Constrained,其他时候设置无效,将会默认为Flexible固定缩放,也就是说当你发布在网页平台的时候设置为ConstrainedOnMobiles为无效操作.

Flexible 意味着保持原有像素,不进行缩放.分辨率的变化不影响UI的像素.

Unity默认按照UI Root Minimum Height 最小高度限制来设定 该UI元素的实际高度.

而且UI Root脚本中 默认最小高度为720px,最大高度为1280px

并且限定范围为320px <=  Height <= 1536px

比如当我们把屏幕的宽高度设置为1280 * 7200 px

那么在固定缩放的情况下,Scaling.Flexible中,实际高度activeHeight是怎么计算的呢?

if (scaling == Scaling.Flexible)
{
Vector2 screen = NGUITools.screenSize;
float aspect = screen.x / screen.y; if (screen.y < minimumHeight)
{
screen.y = minimumHeight;
screen.x = screen.y * aspect;
}
else if (screen.y > maximumHeight)
{
screen.y = maximumHeight;
screen.x = screen.y * aspect;
} // Portrait mode uses the maximum of width or height to shrink the UI
int height = Mathf.RoundToInt((shrinkPortraitUI && screen.y > screen.x) ? screen.y / aspect : screen.y); // Adjust the final value by the DPI setting
return adjustByDPI ? NGUIMath.AdjustByDPI(height) : height;
}

从脚本中我们可以得知,首先通过NGUITools.screenSize获取实际屏幕宽高,然后求出宽高比aspect;

然后根据实际屏幕高度的与minimumHeight和maximumHeight相比取得限定范围内合适的值

  1. 实际屏幕高度比最小高度小,设定实际屏幕高度为最小高度,然后根据比例aspect求出最终宽度;
  2. 实际屏幕高度比最大高度大,设定实际屏幕高度为最大高度,然后根据比例aspect求出最终宽度;
  3. 若实际屏幕高度在最大高度和最小高度之间,则不进行改变.
  4. 若收缩shrinkPortraitUI 且屏幕高度大于宽度,则进行比例压缩,真实高度 = screen.y / aspect ,否则保持不变.
  5. 返回最终结果.

好奇的是,NGUITools.screenSize是怎么获取到我们设定的屏幕大小的呢?

#if UNITY_EDITOR
static int mSizeFrame = -;
static System.Reflection.MethodInfo s_GetSizeOfMainGameView;
static Vector2 mGameSize = Vector2.one; /// <summary>
/// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden.
/// </summary> static public Vector2 screenSize
{
get
{
int frame = Time.frameCount; if (mSizeFrame != frame || !Application.isPlaying)
{
mSizeFrame = frame; if (s_GetSizeOfMainGameView == null)
{
System.Type type = System.Type.GetType("UnityEditor.GameView,UnityEditor");
s_GetSizeOfMainGameView = type.GetMethod("GetSizeOfMainGameView",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
}
mGameSize = (Vector2)s_GetSizeOfMainGameView.Invoke(null, null);
}
return mGameSize;
}
}

原来在编辑器模式中,通过反射获取到类型 System.Type.GetType("UnityEditor.GameView,UnityEditor");  通过类型获取到方法 type.GetMethod("GetSizeOfMainGameView", 最后调用方法得到屏幕大小.

接下来我们用案例来看UI实际情况:首先设置屏幕大小为1270*720ox

把UI Root 的最小Minimum 设置为 720px,也就是以此 UI Root为画布的元素(画布和屏幕大小一致),默认与画布的比例是自身元素高度  :  720px

如我们把Button设置的宽高设置为72 px * 1280 px,那么刚好 10个Button元素就能把画面填充满

最顶部Button元素的坐标Y轴是324,那么它是怎么来的呢?

计算:屏幕高度 / 2 - 元素高度 /2 = 720/2 – 72/2 = 324 px

这在做网格类游戏很有用哦:比如三消游戏或者SLG游戏等

(二) UI Root缩放方式之 Constrained

  1. Constrained is the exact opposite of that. When the UIRoot is set to this setting, your screen will always remain the same size as far as NGUI is concerned, regardless of the actual screen size. This means that if a 300x200 widget takes 25% of your screen with the resolution of 1920x1080, it will still take 25% of the screen when you drop your resolution to 1280x720. If you don't want to worry about how your UI will look at different screen sizes and you don't care much about making it as crisp as possible, choose this setting. Don't forget to set the Content dimensions setting when choosing this option.
  2. You can further refine the constrain by choosing whether the content will Fit on the screen or whether it will Fill the screen (when 'fit' is off). Think of it as your Desktop wallpaper. When you choose the Fit method, the wallpaper will always be fully visible on the screen, where if you go with a Fill method, it will always completely fill the screen while maintaining its aspect ratio. Same idea here. See the attached image for more information.
  3. 译:Constrained 约束缩放方式正好相反,无论你的屏幕分辨率是多少,UI元素将会保持着最适合的缩放方式渲染在屏幕中,元素的大小看起来无论在任何分辨率的设备都是一致的. 只是在低分辨率的设备中,元素会压缩而变得更清晰,但是在高分辨率的设备中,为了保持同等大小,可能会进行拉伸而显得没那么清晰.
  4. 你可以进一步约束,使得它填充满屏幕,并且宽高比不变(也就是说部分元素会溢出在屏幕之外) 根据百分比缩放,大小可能会失真.

(三) UI Root缩放方式之 ConstrainedOnMobiles

  1. ConstrainedOnMobiles setting is a combination of the two. It will behave as if the setting was "Flexible" on desktop builds, and it will act as if the size was "Constrained" when targeting mobile platforms.
  2. ConstrainedOnMobiles设置是两者的结合。它将表现得好像设置桌面构建“灵活”,它的“约束”只是针对移动平台。

UI Root 广播机制

static void UIRoot.Broadcast    (    string     funcName    )
static
Broadcast the specified message to the entire UI. static void UIRoot.Broadcast ( string funcName,
object param
)
static
Broadcast the specified message to the entire UI.

对UI的显示有影响的不只是UI Root的缩放方式,UI 元素的大小,锚点的设置,还有摄像机的Size哦

  1. 对于相同的元素,默认摄像机大小Size为1,UI摄像机使用的是正交投射方式,Size控制正交摄像机的视窗口大小
  2. 当画布大小为1280*720 ,正好铺满画布的元素大小为 1280*720,在Size为1 的摄像机中完美的渲染到屏幕中,不产生任何裁剪和填充
  3. 当我们更改正交摄像机的Size为0.5时,情况是怎样的呢?
  4. 这是为什么呢?因为摄像机在Size为1的时候,能渲染1280*720的像素,当Size减小为一半的时候,意味着摄像机视窗口能渲染的东西少了一半,也就是只有640*320像素元素了,这反而看起来是摄像机Size小了,元素反而还变大了…
  5. 在下节中会详细的介绍Unity中的摄像机,谢谢关注

深挖 NGUI 基础 之UIRoot (一)的更多相关文章

  1. 深挖 NGUI 基础 之UICamera (二)

    一.UI Camera作用 UICamera需要挂载在摄像机上才能发挥作用 UICamera仅负责 发送NGUI 事件 到 脚本所附加的摄像机中看得到的对象,比如我自定义了NGUI层(在Inspect ...

  2. 深挖计算机基础:MySQL实战45讲学习笔记

    参考极客时间专栏<MySQL实战45讲>学习笔记 一.基础篇(8讲) MySQL实战45讲学习笔记:第一讲 MySQL实战45讲学习笔记:第二讲 MySQL实战45讲学习笔记:第三讲 My ...

  3. 深挖计算机基础:趣谈Linux操作系统学习笔记

    参考极客时间专栏<趣谈Linux操作系统>学习笔记 核心原理篇:内存管理 趣谈Linux操作系统学习笔记:第二十讲 趣谈Linux操作系统学习笔记:第二十一讲 趣谈Linux操作系统学习笔 ...

  4. 深挖计算机基础:Linux性能优化学习笔记

    参考极客时间专栏<Linux性能优化实战>学习笔记 一.CPU性能:13讲 Linux性能优化实战学习笔记:第二讲 Linux性能优化实战学习笔记:第三讲 Linux性能优化实战学习笔记: ...

  5. Unity3d ngui基础教程

    Unity3d ngui基础教程 NGUI教程:步骤1-Scene 1.创建一个新的场景(New Scene).2.选择并删除场景里的MainCamera.3.在NGUI菜单下选择Create a N ...

  6. 鸿蒙内核源码分析(文件句柄篇) | 深挖应用操作文件的细节 | 百篇博客分析OpenHarmony源码 | v69.01

    百篇博客系列篇.本篇为: v69.xx 鸿蒙内核源码分析(文件句柄篇) | 深挖应用操作文件的细节 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说 ...

  7. 深挖JDK动态代理(二):JDK动态生成后的字节码分析

    接上一篇文章深挖JDK动态代理(一)我们来分析一下JDK生成动态的代理类究竟是个什么东西 1. 将生成的代理类编程一个class文件,通过以下方法 public static void transCl ...

  8. 深挖JDK动态代理(一)

     最近在研究RPC框架,避免不了的就是在RPC调用中使用最多的则是动态代理的机制了,基于此,我们先来研究一下JDK动态代理 我们先来尝试着编写一下JDK动态代理的代码 1. 由于JDK动态代理是基于接 ...

  9. 深挖Openstack Nova - Scheduler调度策略

    深挖Openstack Nova - Scheduler调度策略   一.  Scheduler的作用就是在创建实例(instance)时,为实例选择出合适的主机(host).这个过程分两步:过滤(F ...

随机推荐

  1. 【luogu P1993 小K的农场】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1993 1.差分约束: 对于a - b <= c 有一条 b-->a 权值为c 对于a - b & ...

  2. normal 普通身份 sysdba 系统管理员身份 sysoper 系统操作员身份 dba和sysdba

    as sysdba 就是以sysdba登录,oracle登录身份有三种:normal 普通身份sysdba 系统管理员身份sysoper 系统操作员身份每种身份对应不同的权限 sysdba权限:●启动 ...

  3. C#实现异步GET的方法

    using System; using System.Collections.Generic; using System.Configuration; using System.IO; using S ...

  4. js使用hover事件做一个“个人中心”的浮动层

    原材料知识点:hover html: css:

  5. oracle 完整性约束的禁用启用以及对表的影响,表的修改和复制

    primary key ----表的唯一性约束,不能为空,且不能有重复值 foreign key ----俩表之间的约束,启用之时,在删除数据时需要先删除父表数据,再删除子表数据 禁用方式为:alte ...

  6. 分组函数group by和Oracle中分析函数partition by的用法以及区别

    1.分组函数group by和Oracle中分析函数partition by的用法以及区别 2.开窗函数.

  7. oracle日常监控语句

    oracle常用的性能监控SQL语句 一.查询历史SQL: ---正在执行的SQL语句: select a.username, a.sid,b.SQL_TEXT, b.SQL_FULLTEXT fro ...

  8. 手机浏览器页面点击不跳转(Android手机部分浏览器) 浏览器双击放大网页 解决

    手机端web网页项目(angluar js 1.4.6) 1,网页项目开发过程中,使用PC浏览器能正常访问,IOS设备浏览器也能正常访问,但是使用Android部分浏览器进行访问的时候,链接偶尔不跳转 ...

  9. Lucas定理及应用

    额,前两天刚讲了数据结构,今天我来讲讲组合数学中的一种奇妙优化——Lucas 先看这样一个东西 没学过lucas的肯定会说:还不简单?处理逆元,边乘边膜呗 是,可以,但注意一下数据范围 你算这一次,你 ...

  10. 洛谷P1731 [NOI1999]生日蛋糕(爆搜)

    题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱 ...