NGUI所见即所得之UIAtlasMaker , UIAtlas

 NGUI所见即所得之UIAtlasMaker , UIAtlas

 

        本文的重点就是要将NGUI把多张图片打成一个图集(Atlas)的原理和过程研究下,学习下Unity提供的api和NGUI写的功能以及设计思想。

 

UIAtlas

       在介绍UIAtlasMaker之前先看下,先看下UIAtlasMaker的产物——UIAtlas,在创建Sprite的时候都要指定UIAtlas,下面先对UIAtlas的代码:

C#代码   收藏代码
  1.        // Material used by this atlas. Name is kept only for backwards compatibility, it used to be public.  
  2. [HideInInspector][SerializeField] Material material;  
  3.   
  4. // List of all sprites inside the atlas. Name is kept only for backwards compatibility, it used to be public.  
  5. [HideInInspector][SerializeField] List<UISpriteData> mSprites = new List<UISpriteData>();  
  6.   
  7. // Size in pixels for the sake of MakePixelPerfect functions.  
  8. [HideInInspector][SerializeField] float mPixelSize = 1f;  
  9.   
  10. // Replacement atlas can be used to completely bypass this atlas, pulling the data from another one instead.  
  11. [HideInInspector][SerializeField] UIAtlas mReplacement;  
  12.   
  13.        // Whether the atlas is using a pre-multiplied alpha material. -1 = not checked. 0 = no. 1 = yes.  
  14. int mPMA = -1;  

      可以很惊奇的发现UIAtlas的成员变量竟然极其精简,就只有:Material material;      UISpriteDatat的List mSprites;      每个像素的大小 mPixelSize 这个跟UIWidget的像素大小应该是类似的,  UIAtlas mReplacement; 这个目前只能望文生义,虽然知道是用来替换UIAtlas,但好像没有发现哪里会有用到,在UISprite的那里只是选择不同的UIAtlas而不是替换UIAtlas本身,就暂且搁置,   最后一个是mPMA这个是pre-multiplied的像素存储技术,大致了解下,好像是把alpha的值存储在每个颜色的RGB中去已达到节省存储空间的技术,想要了解更多可以自行google下。

      接着看UIAtlas,接下来就是把属性的{get,set} 以及几个函数,也很简单,主要就是属性改变,就调用MakeAsDirty()函数,下面看下这个函数的前面一部分:

C#代码   收藏代码
  1. public void MarkAsDirty ()  
  2.     {  
  3. #if UNITY_EDITOR  
  4.         UnityEditor.EditorUtility.SetDirty(gameObject);  
  5. #endif  
  6.         if (mReplacement != null) mReplacement.MarkAsDirty();  
  7.   
  8.         UISprite[] list = NGUITools.FindActive<UISprite>();  
  9.   
  10.         for (int i = 0, imax = list.Length; i < imax; ++i)  
  11.         {  
  12.             UISprite sp = list[i];  
  13.   
  14.             if (CheckIfRelated(this, sp.atlas))  
  15.             {  
  16.                 UIAtlas atl = sp.atlas;  
  17.                 sp.atlas = null;  
  18.                 sp.atlas = atl;  
  19. #if UNITY_EDITOR  
  20.                 UnityEditor.EditorUtility.SetDirty(sp);  
  21. #endif  
  22.             }  
  23.         }  
  24.             ……  
  25.         }  

 可以看出这个函数其实就是更新以replacemet和this为UIAtlas的UISprite的UIAtlas,就是这么简单。

 

 UISpriteData

       在UIAtlas中有GetSprite()和GetListOfSprites(),其中GetSprite返回的UISpriteData,让人不得不猜想UISpriteData就是UISprite中的图片,但其实它只是一个结构体:

C#代码   收藏代码
  1. public class UISpriteData  
  2. {  
  3.     public string name = "Sprite";  
  4.     public int x = 0;  
  5.     public int y = 0;  
  6.     public int width = 0;  
  7.     public int height = 0;  
  8.   
  9.     public int borderLeft = 0;  
  10.     public int borderRight = 0;  
  11.     public int borderTop = 0;  
  12.     public int borderBottom = 0;  
  13.   
  14.     public int paddingLeft = 0;  
  15.     public int paddingRight = 0;  
  16.     public int paddingTop = 0;  
  17.     public int paddingBottom = 0;  

       一看这些成员变量,就会感觉很熟悉,这不是就是UI组件的基本熟悉么,可以进一步看下UIInspectorEditor界面,就更加确信了,而且Border其实用在SliceSprite的,至于Padding就是空白不显示区域,而且x,y,width,height其实该图片就是在UIAtlas上Rect区域。

 

      也就是说,UISpriteData根本没有实际记录图片的像素信息,而只是记录图片在UIAtlas生成的那张大图的坐标,宽度和高度,以及图片拉伸的一些信息(Border,Padding)。

 

UIAtlasMaker

      从前面的分析,可以大概知道UIAtlasMaker的原理:把多张图片合并成一张大图,记录每张图片的在生成的大图的坐标和大小。下面将使用介绍算法那种思路把UIAtlasMakder的工作流程描述清楚。

      在详细介绍之前,UIAtlasMakder定义了UISpriteEntry这个类:

C#代码   收藏代码
  1. class SpriteEntry : UISpriteData  
  2.     {  
  3.         // Sprite texture -- original texture or a temporary texture  
  4.         public Texture2D tex;  
  5.           
  6.         // Whether the texture is temporary and should be deleted  
  7.         public bool temporaryTexture = false;  
  8.     }  

       只是在UISpriteData基础上扩展了一个Texture2D tex的成员变量,那么这个类到底做什么用呢?通过分析代码可以知道:UISpriteEntry是UISpriteData和Texture2D的中间体,是Texture2D和UISpriteData转化的载体,就提过程下面会有引人。

 

 

UIAtlasMaker的工作流程:

1)选择图片or图集,函数:void OnSelectAtlas (Object obj) 和 List<Texture> GetSelectedTextures ()

2)导入选择图片的Texture2D,函数:static List<Texture2D> LoadTextures (List<Texture> textures)

3)将Texture2D转出UISpriteEntry,函数:static List<SpriteEntry> CreateSprites (List<Texture> textures) ,这个函数中包括了2)的步骤

3)打包成大图片并生成UISpriteData,函数:static bool PackTextures (Texture2D tex, List<SpriteEntry> sprites),这个函数提供两种打包方式:1.NGUI自己实现类UITextPacker,2.Unity3D提供的api

4)释放UISpriteEntry,函数:static void ReleaseSprites (List<SpriteEntry> sprites),主要是通过NGUITools.Destroy销毁纹理,最后调用Resources.UnloadUnusedAssets();,这个趁机告诉我们Unity中资源销毁的方法,一个不能少哈。

C#代码   收藏代码
  1. static void ReleaseSprites (List<SpriteEntry> sprites)  
  2.     {  
  3.         foreach (SpriteEntry se in sprites)  
  4.         {  
  5.             if (se.temporaryTexture)  
  6.             {  
  7.                 NGUITools.Destroy(se.tex);  
  8.                 se.tex = null;  
  9.             }  
  10.         }  
  11.         Resources.UnloadUnusedAssets();  
  12.     }  

 

差不多就是这样子,其他就是一些功能操作:add,replace,delete,udpate,extract。

 

       这样看来,把UIAtlas分析清楚,掌握UIAtlasMaker的原理应该不难,当然里面有很多细节,使用很多api:AssetDatabase,Texture,SelectedObject以及NGUI自己封装的一些函数。

 

 

小结:

       UIAtlas虽然在使用NGUI过程中用的太多了,但是经过上面的分析,其实不是很难,个人觉得还没有UIRoot(NGUI所见即所得之UIRoot)的难以驾驭,即使UIRoot很短很单一。这里说下D.S.Qiu的关于快速学习的一点体会:古人有云,“工欲善其事,必先利其器”,NGUI最为一个工具,要使用好它,就要充分掌握它, 换句话说就要懂它,当然还可以从中偷到很多师——功能的具体实现和代码逻辑的设计,其实一直觉得我对细节都不求甚解,会用就可以走路了,又不用自己写一个NGUI,当然细节都能掌握就更完美了。已经到凌晨一点了,先写这么多,有补充在加。

         如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.qiu@gmail.com)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。

        转载请在文首注明出处:http://dsqiu.iteye.com/blog/1967088

更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值