UGUI学习笔记

【旧博客转移 - 2016年7月7日 23:13 

 

最近用了下UGUI,毕竟是Unity官方内置的,估计以后也会慢慢取代NGU了,现在资料也还算丰富

图集打包方式

看了雨松MOMO的几篇文章UGUI研究院之全面理解图集与使用(三),看完后自己弄了一些图片实验了一下

sprite packer

这是UGUI自带的打包工具,同一个图集这里面会很智能的分成多个小图集,纹理格式不同(多张小图集是怎么合并渲染的?)

Sprite图片设置相同的packingTag就会打包到一个图集里,但是我发现Unity5.3.5版本的UGUI下,两张图设置不同的pack tag,居然只有1个setPass Call。而Unity4.6.7版本的UGUI下 ,两张图设置不同的pack tag就是2个drawCall。这点比较神奇~

但我还是觉得UGUI的自带图集不好用!(可能我还没搞懂,不会用~ 哈哈)

1.不是最小矩形,会多空白区域占内存(已经选了TightPackerPolicy 不是最小矩形)

2.加载/释放不可控,貌似进入游戏就会全部加载进内存(用profiler看)

3.资源热跟新不好控制

建议用还是用TexturePacker自己写Atlas去控制

UGUI的结构

下载了UGUI源码粗略的看了一下,网上也有很多教程编译、调试源码的方法

UGUI的结构简单清晰,Image继承了MaskableGraphic->Graphic,

Graphic(控制渲染显示类,图片什么的最终都继承它)

Graphic类中的OnPopulateMesh方法会去生成顶点,三角形数据,用一些dirty变量控制重绘。

VertexHelper类:存放uv,vertex,color等数据。

其中核心的渲染部分CanvasRender代码Unity并没有开源,封装在了UnityEngine里面.. 所以看不到它是怎么合并贴图渲染的。

UGUI的默认Shader

UGUI图片的默认材质是在Graphic.defaultGraphicMaterial

这里面调用Canvas.GetDefaultCanvasMaterial()这个方法获取的。

自带的Shader可以在官网上下载的到

Shader "UI/Default"
{
 Properties
 {
 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
 _Color ("Tint", Color) = (1,1,1,1)

 _StencilComp ("Stencil Comparison", Float) = 8
 _Stencil ("Stencil ID", Float) = 0
 _StencilOp ("Stencil Operation", Float) = 0
 _StencilWriteMask ("Stencil Write Mask", Float) = 255
 _StencilReadMask ("Stencil Read Mask", Float) = 255

 _ColorMask ("Color Mask", Float) = 15

 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
 }

 SubShader
 {
 Tags
 {
 "Queue"="Transparent"
 "IgnoreProjector"="True"
 "RenderType"="Transparent"
 "PreviewType"="Plane"
 "CanUseSpriteAtlas"="True"
 }

 Stencil
 {
 Ref [_Stencil]
 Comp [_StencilComp]
 Pass [_StencilOp]
 ReadMask [_StencilReadMask]
 WriteMask [_StencilWriteMask]
 }

 Cull Off
 Lighting Off
 ZWrite Off
 ZTest [unity_GUIZTestMode]
 Blend SrcAlpha OneMinusSrcAlpha
 ColorMask [_ColorMask]

 Pass
 {
 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag

 #include "UnityCG.cginc"
 #include "UnityUI.cginc"

 #pragma multi_compile __ UNITY_UI_ALPHACLIP

 struct appdata_t
 {
 float4 vertex : POSITION;
 float4 color : COLOR;
 float2 texcoord : TEXCOORD0;
 };

 struct v2f
 {
 float4 vertex : SV_POSITION;
 fixed4 color : COLOR;
 half2 texcoord : TEXCOORD0;
 float4 worldPosition : TEXCOORD1;
 };

 fixed4 _Color;
 fixed4 _TextureSampleAdd;
 float4 _ClipRect;

 v2f vert(appdata_t IN)
 {
 v2f OUT;
 OUT.worldPosition = IN.vertex;
 OUT.vertex = mul(UNITY_MATRIX_MVP, OUT.worldPosition);

 OUT.texcoord = IN.texcoord;

 #ifdef UNITY_HALF_TEXEL_OFFSET
 OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
 #endif

 OUT.color = IN.color * _Color;
 return OUT;
 }

 sampler2D _MainTex;

 fixed4 frag(v2f IN) : SV_Target
 {
 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;

 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);

 #ifdef UNITY_UI_ALPHACLIP
 clip (color.a - 0.001);
 #endif

 return color;
 }
 ENDCG
 }
 }
}

 

它跟NGUI一样也是用renderQueue控制渲染深度,但UGUI是使用Stencil模板测试来做遮罩的,所以如果重写UGUI的Shader想要支持Mask的话,就要加上Stencil的代码。

实现灰度图

非常简单,改写一下默认的Shader,在frag中加上灰度值转化的代码。

新建一个Material,挂上这个Shader,然后给要灰掉的图片使用这个材质就OK了,而且支持裁剪。

总结

UGUI使用很方便,分辨率自适应,锚点这些都很好控制。 而且它能吧Text跟Image都合并成一个pass(感觉整个Canvas下都会合并成1个pass) 不知道这样究竟能不能提高性能,表面上是减少了setPassCall,但我觉得上只要Image,或Text有改动,就会重新计算整个Canvas下所有组件合并网格。一些频繁变化的东西,还是弄成独立的Canvas好,比如血条,瓢字之类的。 现在只是大概了解了一下UGUI,还不太熟悉,如果我有理解的不对的地方欢迎留言交流哈~  

posted @ 2017-05-16 15:26  李嘉的博客  阅读(1202)  评论(0编辑  收藏  举报