ar ngui unity3d
2014-06-04 23:32:36 code_monkey 阅读数 522

  12年的时候使用过ngui,现在3.5以后的版本与老版本的底层实现有很大差别,一个个控件的使用在了解原理后都是相对简单的事情。

UIRoot, ngui的根节点,设置ngui总体显示的分辨率相关参数。

UICamera, ngui的camera脚本,挂在一个正交摄像机上,负责事件相关设置,事件类型,事件对象设置,事件源,事件灵敏度等。

UIWidget, 基本绘制类型,这是3.5以后版本与老版本的最大不同,绘制都是通过UIWidget中的方法实现,主动调用unity3d的绘制api绘制,而不是像老版本一样动态生成,mesh挂置在对应gameobject上,实现动态批次调整的更好控制。

触摸点击事件之类的,通过Box Collider的射线检测来实现,然后调用对应回调实现消息处理。


基本原理就是正交摄像机绘制对应ui元素,通过射线检测Box Collider碰撞来实现触摸检测和响应。


新版本的ngui加入了多语言支持、ttf以及bmfont支持、scrollview等高级控件的支持,总体功能比较强大且易用。


通过atlas的拼接来优化drawcall,实现更高效渲染。

2014-06-20 13:49:41 zxsean 阅读数 798

原文地址:http://dsqiu.iteye.com/blog/1964679


  UIRoot是NGUI最根本和最重要的脚本,在实际UI开发过程中都是以UIRoot为根的GameObject树,那他的作用到底是什么,先看下UIRoot的Inspection选项:

看到这个,大致可以猜到是跟UI界面缩放有关的,而且是基于高度放缩的。

 

Scaling Style参数

 

       到底每个参数(Scaling Style, Manual Height ,Minimum Height 和MaximumHight)的作用和区别是什么,在没有其他先验知识的情况下,只有去看代码了。

       

C#代码  收藏代码
  1. public enum Scaling  
  2.     {  
  3.         PixelPerfect,  
  4.         FixedSize,  
  5.         FixedSizeOnMobiles,  
  6.     }  

       Scaling Style参数的作用是制定UIRoot的缩放类型,如果是PixelPerfect,Minimum Height和Maximum Height才起作用,换而言之,如果Scaling Style选择的是PixelPerfect就要对Minimum Height和Maximum Height进行设置。FixedSize和FixedSizeOnMobiles只跟Manual Height有关,区别在于后者(FixedSizeOnMobiles)只是针对IOS和Android上的判断,也就是说只有IOS和Android平台下FixedSizeOnMobiles才起作用。

       那他们是怎么缩放的呢?如果是PixelPerfect缩放类型,当屏幕的分辨率大于Maximum Height,则以Maximum Height 为基础缩放,反之,如果屏幕分辨率小于Minimum Height 则以Minimum Height为基础进行缩放。例如,如果屏幕高度为1000,而设置的Maximum Height值为800,则UI界面整体放大为原来的1000/800=1.25倍。

       如果Scaling Style指定为FixedSize或FixedSizeOnMobiles,则缩放只以Manual Height为参考,屏幕分辨率的高度值不同于此设置值时,则根据其比例(即Screen Height / Manual Height)对整棵UI树的进行“等比”缩放(宽度的缩放比也是此比例值)。

 

      如果Scaling Style指定为FixedSize,UIWidget.height(以UIRoot默认进行高度缩放)是不会改变的(有关UIWidget的内容可以查看D.S.Qiu的另外一篇文章),不管实际屏幕分辨率的像素是多少,这看下Example 1 的 Anchor Stretch的背景图片,高度始终都是800,即设置的的manualHeight:

        也就是相当于UIRoot下的UIWidget的height参数一直都是实际的值,虽然在实际在显示器显示的高度不是UIWidget.height这个值,所以才有了放缩的感觉。实际的放缩是根据Camera.pixelHeight(这个值和Screen.height的大小是一样的)来的,也就是放缩比 = Camera.pixelHeight/UIRoot.manualHeight,或者是Screen.height/UIRoot.manualHeight。

         也就是说,当Scaling Style 指定为FixedSize,UIRoot的子对象高度的参数保持不变,至于显示的缩放是根据Camera自动进行的,程序无需额外控制。更多详细的分享可以参考另外一篇有关UIAnchor 和UIStretch的文章(猛点查看)。

                                                                                                                                           增补于 2013/11/16 14:20

 

Scaling Style策略       

 

(1)PixelPerfect和Minimum Height, Maximum Height

使用PixelPefect,只要是想达到UI图片尽可能不缩放,保持原尺寸大小,这种在PC端这种可以调节界面大小的会使用比较多。

(2)FixedSize和Manul Height

FixedSize只要是希望UI界面尽可能和屏幕分辨率适配,如移动设备上,特别是手机上,屏幕就那么小,UI界面一定要求全屏显示,就要进行缩放。

 

       对于Unity实际开发中屏幕自适应问题,oneRain在①中有更详细的描述,这里只介绍下,D.S.Qiu想到的一种自适应策略——“花草”填充法。填充法(这个是D.S.Qiu命名的,哈哈,自恋下)指的是用其他图片区填充因为固定比例放缩而出现镂空黑边的区域,当然也可能已经有游戏是这么做的,当然oneRain说的增加一个宽度缩放比例,长宽分别以尽可能接近屏幕长宽比的比例去缩放。

 

Scale的实现

       虽然我们已经了解了Scale的作用区别以及策略,那到底是怎么实现的呢?还是上代码:

C#代码  收藏代码
  1. void Update ()  
  2.     {  
  3.         if (mTrans != null)  
  4.         {  
  5.             float calcActiveHeight = activeHeight;  
  6.             if (calcActiveHeight > 0f )  
  7.             {  
  8.                 float size = 2f / calcActiveHeight;  
  9.                 Vector3 ls = mTrans.localScale;  
  10.       
  11.                 if (!(Mathf.Abs(ls.x - size) <= float.Epsilon) ||  
  12.                     !(Mathf.Abs(ls.y - size) <= float.Epsilon) ||  
  13.                     !(Mathf.Abs(ls.z - size) <= float.Epsilon))  
  14.                 {  
  15.                     mTrans.localScale = new Vector3(size, size, size);  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  

       可以看出Update函数中是根据activeHeight来调整UIRoot的transform的localScale来实现的,哈,竟可以这么简单。那么,我们只要弄清楚activeHeight就可以了:

C#代码  收藏代码
  1. public int activeHeight  
  2.     {  
  3.         get  
  4.         {  
  5.             int height = Mathf.Max(2, Screen.height);  
  6.             if (scalingStyle == Scaling.FixedSize) return manualHeight;  
  7.  
  8. #if UNITY_IPHONE || UNITY_ANDROID  
  9.             if (scalingStyle == Scaling.FixedSizeOnMobiles)  
  10.                 return manualHeight;  
  11. #endif  
  12.             if (height < minimumHeight) return minimumHeight;  
  13.             if (height > maximumHeight) return maximumHeight;  
  14.             return height;  
  15.         }  
  16.     }  

       可以看出activeHeight就是前面Scale Style的不同参数的具体实现,即得到缩放参考高度。

 

Orthographic Size和分辨率

       

       在上面Update和activeHeight的函数中都出现了  “2” 这个常数,这个常数到底是怎么来的。要想知道这个,就要明白Camera 设定为Orthographic类型中的Size(即Orthographic Size)的含义,查看Unity文档,就可以知道这个Size是Camera看到区域的一半,如果Size设置为1,则Camera可以看到高度为为2的区域,然后我们知道照相机看到的区域是全画在整个屏幕的,也就是说Size的值对应为屏幕分辨率的一半。

        如果屏幕宽度为1000个像素,Size设置的值表示1000/2=500个像素。所以,我们通过整个关系计算UIRoot下的GameObject的实际对应屏幕的高度:从GameObject向上一直到UIRoot,将它们的loaclScal相乘得到的乘积除以Size乘以屏幕高度的一半,即(localScale*....localScale)/Size*Screen.height/2。

        这可以解释UIRoot的localStyle为啥都是很小的小数,因为这样可以保证UIRoot的子节点都可以以原来的大小作为localScale,比如一张图片是20*20的,我们可以直接设置localScale为(20,20,1)不用进行换算,直观方便。(NGUI3.0(or 2.7)以后的版本已经不再使用localScale来表示UISprite ,UILable(UIWidget的子类)的大小了,而是在UIWidget的width和height来设置,这样做的好处就是一个gameObject节点可以挂多个UISprite或UILabel了,而不会受localScale的冲突影响    2013/11/16增补)。

 

 

UIRoot细节

      前面说道Update函数中有一个常数 2 ,表示Size是设置为1的,这个可以从Start函数就可以知道:

C#代码  收藏代码
  1. protected virtual void Start ()  
  2.     {  
  3.         UIOrthoCamera oc = GetComponentInChildren<UIOrthoCamera>();  
  4.         if (oc != null)  
  5.         {  
  6.             Debug.LogWarning("UIRoot should not be active at the same time as UIOrthoCamera. Disabling UIOrthoCamera.", oc);  
  7.             Camera cam = oc.gameObject.GetComponent<Camera>();  
  8.             oc.enabled = false;  
  9.             if (cam != null) cam.orthographicSize = 1f;  
  10.         }  
  11.         else Update();  
  12.     }  

      但是这里似乎有点疏忽,这里只移除UIOrthoCamera这个脚本(UIRoot脚本开始就言明这两个脚本不能同时使用,所以要移除),并将cam的orthographicSize设置为1f,但是我想如果没有UIorthoCamera这个脚本的话,就不会重新设置Camera的orthographicSize值,这样如果orthographicSize不是1的话,效果就不一样了。刚开始我会以为这是NGUI developer的一个Bug,但是如果都在Start设置orthographicSize为1f,那这个参数就没有意义了,让使用者自己设置可以有更多效果,如“屏中屏”——将满屏的UI缩放为另外一个UI界面的一半大小,所以才会说“似乎有点疏忽”。

      下面看下效果图:


  orthographicSize=1
  orthographicSize=2

        很明显可以orthographicSize=2时,图片进行了缩小。当orthographicSize=1时背景图片用了UIStretch脚本来实现满屏效果,当orthographicSize为2时却没有满屏,这就说明代码中UIRoot是以2为屏幕宽度的,现在Camera的视野大小为4,那映射到屏幕当然不会有“满屏”的效果了(只会是屏幕宽度的一半),背景图片在左上角是因为使用UIAnchor脚本。

         ②和③中分别都介绍了如何设置Orthographic Size来达到像素和Unity中单位对应起来,都写的很不错,这也是我写这篇博客的一个触动。

     

         UIRoot中还有两类函数:GetPixelSizeAdjustment 和 Broadcast,前者是获取当前分辨率的单个像素的大小,而后者其实就一个UIRoot的消息广播函数,还有一个当前激活状态下的UIRoot的队列。至此D.S.Qiu已经将UIRoot脚本解析的淋漓尽致了,自然就剩下小结了。

 

基于宽度放缩

       

        UIRoot是基于高度放缩的,即放缩的比例是以高度为参考的,所以UIRoot有一个manualHeight的参数。那么对于横版游戏显然不行,要是能实现基于宽度放缩。所以可以通过设置一个“manualWidth”的参数来做。比如我们项目中使用的是 1024 作为UI的宽屏尺寸,通过换算设置manualHeight的值:

 

C#代码  收藏代码
  1. int height = Mathf.Max(2, Screen.height);  
  2. manualHeight = Screen.height * 1024 / Screen.width; //基于宽度的屏幕分辨率自适应  

        之前的同事用了很多方法都没有搞定,其实根本就没有那么复杂,所以一旦知道原理之后,很多事情就变得简单多了。

                                                                                                                     增补于  2013,12,23             22:14



2014-05-10 09:37:25 GSA1234 阅读数 187

NGUI确实是非常棒的一个做界面的插件,比起U3D自带的GUI要好很多,当然也有一些不好之处,毕竟什么都不可能那么完美。

 

最近在用Unity写游戏使用NGUI遇到了一个很多人都在遇到的问题,就是关于屏幕自适应,谷哥度娘里面写关于适应屏幕的帖子很多,但是大多都是 一样抄来抄去,都是说是Panel里面加个UIStretch里面加个 if 分支,什么OnWidth什么的,还要把UIAnchor的side放置在Bottom等等步骤,过于麻烦,而且效果也一般。

 

不知道大家在用最新的Unity的时候在UIStretch里面style参数有没有发现新添加了两个枚举

按照它的字面意思就是一个是“按保持的比例填充”和“适合保持内部比例”

 

其实可以想一想,安卓手机在屏幕分辨率上面有很多种,其长宽比例是不一样的,在制作游戏的时候如果保持位置的不变,难免要造成图片的不均等拉伸,所以用原有的比例会使画面看起来更和谐,多出来的部分也并不多,如果可以这样想,那么就可以进行后面的了。

 

1.首先在你的panel里面不要填充任何控件,如果有,可以先拖出来,

2.选中panel添加UIStretch脚本

3.将style选择最后一个FitInternalKeepingRatio

4.在Initial Size中填写你当前使用的屏幕大小。(比如你的游戏视窗是800*480的,就X 800,Y 480)

5.如果原先有控件了,再拖进来就可以了,如果没有,就可以在里面添加控件了。

 

在你选择修改游戏屏幕大小后,一定要运行一下才可以看到它调整过后的效果,可以看到比例是完全适应的,差别仅仅是多出来部分扩大了一些游戏场景而已。

操作起来很容易,也不需要多余的代码。

2013-12-07 12:40:22 u012091672 阅读数 3933

原文:http://www.tasharen.com/forum/index.php?topic=6733.0

NGUI讨论群:333417608

概述


UIScrollBar用来创建滚动条——可变长度的滑动条在大小固定的区域移动。它继承了所有UIprogressBar的功能,仅仅修改了前景的显示方式,变为可以被移动位置并且可以交互。



UISlider类似,UIScrollBar需要引用一个Foreground widget。当Size值为1(100%)的时候,这个widget就会占用滚动条的最大尺寸。

想创建一个简单的滚动条,首先创建一个sliced sprite,之后width和height分别设置为300和30。这就是滚动条的Background

之后增加一个子sliced sprite,这个就是Foreground。这个sprite就是Value为1的时候看起来的样子。你可以把这个sprite封装到父节点里面,这样看起来更合理。

做完以上内容之后,挂一个UIScrollBar给背景sprite,之后设置相应的ForegroundBackground属性。点击Play之后在Inspector窗口调整value的值,你就会看到相应的变化。

给滚动条加入Box Collider可以让它变得可以交互。可以分别给Foregrou和Background增加box collider。同时加上UIButton的话就可以让这些sprite可以高亮。


如果你用了两个collider的话,那就要加两个UIButton,一个高亮前景,一个是背景。

在前景上加一个UILabel来让label和前景一起移动(可以用来显示当前的值)。

Direction用来控制value从0到1变化的时候,滑块的移动方向。

OnValueChange属性可以指定功能函数,当滚动条的value变化的时候调用。如果按照上面的方式加入了label,你可以通过调用label的SetCurrentPercent函数,之后这个label就会以百分比的形式显示滚动条的值。把这个label的game object拖拽到Notify属性里面,之后在下拉框里面选择UILabel.SetCurrentPercent。


小贴士

UIStretch放在前景上来让前景的大小跟着背景的变化而变化。

类文档

http://tasharen.com/ngui/docs/class_u_i_scroll_bar.html

2013-12-06 23:21:22 u012091672 阅读数 3220

原文:http://www.tasharen.com/forum/index.php?topic=6738.0

NGUI讨论群:333417608

概述


UIProgressBar是UISliderUIScrollBar的基类。但是你也可以用它来创建进度条——没有滑块的slider。



UIProgressBar用来实现功能的唯一需求就是设置一个Foreground widget。当UIProgressBar的Value是1(100%)的时候,这个foreground widget显示的就是它可填充的最大尺寸。

一个新的进度条只需要创建一个sliced sprite,指定它的width和height为300和20。

接着挂一个UIProgressBar脚本到这个sprite(就是背景)上,设置对应的Foreground。现在点击Play,之后在Inspector窗口里面调整value的值,你就能看到sprite会有相应的变化。

修改Direction属性来调整当value由0到1变化时,进度条的变化方向。

如果想让进度条可以有交互(拖动等),可以看UISlider。


在OnValueChange部分,你可以指定一个功能函数,这个函数会在进度条值变化的时候调用。比如你已经加了一个label,你可以在值变化的时候通过调用label的SetCurrentPercent函数,让label显示当前的进度值。 这个功能的实现方式就是把Label的game object拖动到Notify属性里,之后在下拉列表里面选UILabel.SetCurrentPercent就可以。

小贴士

进度条的foreground不一定非要用sprite。你可以用设置成“ClampContent”、Max Lines是1的UILable。当进度条值增大的时候,就会用UILabel的文本填充进度条。

类文档

http://tasharen.com/ngui/docs/class_u_i_progress_bar.html

Unity3d ngui基础教程

阅读数 715

NGUI教程:步骤1-Scene      更多精彩请关注【狗刨学习网】    1.创建一个新的场景(NewScene)。    2.选择并删除场景里的MainCamera。    3.在NGUI菜单下选择CreateaNewUI,会打开UI创建向导。       

博文 来自: Carl180

Unity3D之NGUI的优化

阅读数 521

转载自:http://blog.csdn.net/zzxiang1985/article/details/43339273一共9招。 1资源分离打包与加载   游戏中会有很多地方使用同一份资源。比如,有些界面会共用同一份字体、同一张图集,有些场景会共用同一张贴图,有些会怪物使用同一个Animator,等等。可以在制作游戏安装包时将这些公用资源从其它

博文 来自: yuxikuo_1

【Unity3D】【NGUI】UIButton

阅读数 8311

原文:http://www.tasharen.com/forum/index.php?topic=6708.0NGUI讨论群:333417608概览Button是一个组件,有以下功能:接收hover、pressed、click事件,修改背景sprite颜色。ImageButton组件可以和Button同时加到一个gameobject上,ImageButton用来切

博文 来自: u012091672

Unity3D NGUI中文支持

阅读数 3438

中文显示支持NGUI添加制作字库,具体参考http://1vr.cn/article.asp?id=607中文代码输入支持使用文本编辑器修改使用了中文的代码文件为utf8-bom格式。一定要加bom头。我使用的是notepad++格式->UTF8格式编码。不然输出是乱码。

博文 来自: heartrude

【Unity3D】【NGUI】UIStretch

阅读数 2470

***3.0.7中不建议使用***这个组件在NGUI的3.0.7版本中不建议使用. Widgets和Panels有新的控制段.OverviewUIStretchmakesitpossibletostretchwidgetsrelativetootherwidgetsorthecamera'sviewrectangle.Whenused

博文 来自: u012091672
没有更多推荐了,返回首页