最近的工作跟 UI 打交道比较多, 各种坑.

  今天从 Prefab 的序列化功能来说说 System.Diagnostics.Conditional 的妙用.

  我们做 UI 面对各种按钮, 组件的获取方式大致也就两种, 一种直接序列化到 Prefab 中, 另一种是在代码中去获取 :

序列化

tagObj = transform.Find("Child/Cube").gameObject; // 代码获取

  各有各的好处 :

    序列化很直接, 代码都不用写了, 并且随便你拖动 UI 到哪个节点, 都能正确引用. 不过问题也很明显, 过了几天连自己都找不着北了, 有过长期维护经验的人应该了解.

    代码获取的方式从维护性来说, 直接就能让看的人知道那个组件在哪个节点上, 理解起来更简单. 可是如果节点路径发生变更, 就要出问题了, 这在频繁改动的 UI 设计上来说很要命. 特别是如果使用封装好的函数进行安全获取, 就更难发现问题了, 比如:

    // 封装好的函数, 连错都不报
public static GameObject GetGameObject(Transform from, string find)
{
var trans = from.Find(find);
if(trans)
{
return trans.gameObject;
}
return null;
}

  如果从效率的角度来看, 应该是序列化 Prefab 的效率要高于使用代码查找的效率的, 因为序列化对象是一个唯一ID, 而代码查找时 Transform 的子对象是在列表中的, 所以 Find 函数查找效率是跟 List 一样的 :

  这里用 tagObj 引用了自己, 看到序列化对象的 ID 就是指向上面的 m_GameObject 的, 应该就是个内部 GUID 了. 从效率上看略胜一筹, 因为我在之前的项目碰到过有几千个 Child 的节点, 然后通过数据库得到的几千个数据对节点下面的对象进行查找, 那效率简直酸爽, 有这种需求的一定要先厉遍 Transform 把所有节点都放到 Dictionary 里引用啊, 血的教训...

  第二点, 存储大小 :

    如果序列化到 Prefab 里面, 它使用了 ID 作为引用, 增加的存储大小基本是个定值, 并且打包之后还能进行压缩等, 实际占用空间非常小, 而且作为资源它可以热更.

    代码如果写在 C# 中, Find("XXX/ooo") 里面的字符会被放到静态域中, 这就很要命了, 因为到项目后期不仅由于过多的代码, 更多的字符串导致程序包过大, 我们真的碰到过超过 IOS 50多M限制的单个 DLL 问题...当然如果写在 Lua 中的话就跟资源一样了, 你能编译成二进制, 你能压缩, 万能的 Lua. 不过按照一般情况, "XXX/ooo" 字符一般都会比 ID 更长特别是 UI 层级很深的情况, 有中文的时候就更糟了.

  假设我们有了 Lua, 你问问开发人员他们愿意写一大堆 Find 代码, 还是简单拖一拖了事? 因为 Lua 在使用上跟 C# 没有什么不同, 如果使用了序列化谁都懒得再去写代码了... 这真的是少有的 Unity 官方功能比民间方法更牛的特例.

  这样看来序列化真是又简单又高效, 还省空间, 主要问题还是在后期维护上, 比如我们的变量叫 tagObj, 制作的人可能引用的对象名称是 Cube, 名称上完全没有关联性, 在一些不可预知的情况下如果引用丢失了, 连制作者都不知道原来引用的是哪个对象的情况多的是. 我们能把两种模式结合起来的话就好了, 比如在组件上面加个注释 :

  恩, 不错, 还有更好的 :

  System.Diagnostics.Conditional 可以根据编译条件决定是否编译,  它在非编辑器下就跟注释一样是不会加进去的, 而在编辑器下你是可以通过 GetCustomAttributes 获取的, 那么它的用处就大了 :

  1. 在编辑器下检查序列化对象是不是丢了, 丢了的话找 Attribute 然后通过 loadPath 去自动获取.

  2. 在编辑器下检查序列化对象跟 loadPath 的对象是不是一致, 检查数据正确性.

  这些看似简单的功能, 在发布版本之前可能救不少人的命呢, 避免了每次抓人去祭天. 通过这个应用方法添加了一些信息, 并能提供上述功能支持.

测试一下 :

-------- 编辑器 --------

-------- 发布后 --------

System.Diagnostics.Conditional 的妙用 -- 把文档放在代码中的更多相关文章

  1. System.Diagnostics.Conditional

    [System.Diagnostics.Conditional] 指示编译器当特定的宏定义了时,才生成此方法的相应代码.只能应用于AttributeClass.Method. 参考:http://ms ...

  2. 小讲堂:Mobox文档管理软件中的文件外链是什么?

    今天我们来讨论Mobox文档管理软件中的文件外链是什么?熟悉MOBOX的朋友们应该知道,如果有文件需要分享给其他同事,直接可以进行文件共享.对方会在AM的即时通讯客户端有消息提醒,点击消息提醒可以看到 ...

  3. 小讲堂:在线编辑在Mobox文档管理软件中的意义

    今天我们来讨论一下,mobox文档管理软件中的在线编辑的这个功能,相信这个功能是用户在日常的文档维护中非常需要的. 文档管理软件的诸多功能中,在线编辑是一块很重要的功能点,因为在线编辑可以说是提高工作 ...

  4. 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览

    ### 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览 http://segmentfault.com/a/1190000002583569

  5. 随时发布:REST API文档的代码仓库中的持续集成与协作

    本文主要内容:API文档提供了预测客户成功的关键路径:在代码附近的文档上进行协作可以更好地检查代码和文档文件,提高自动化效率,并专门针对文档进行质量测试:提供通用文档框架,标准,自动化和工具,以提高团 ...

  6. C#读取Word文档内容代码

    首先要添加引用com组件:然后引用: using Word = Microsoft.Office.Interop.Word; 获取内容: /// /// 读取 word文档 返回内容 /// //// ...

  7. 将word文档A表格中的内容拷贝到word文档B表格中

    Function IsFileExists(ByVal strFileName As String) As Boolean ) <> Empty Then IsFileExists = T ...

  8. 在Eclipse中如何关联spring-framework的文档和源代码

    1.到官方网站去下载spring-framework的jar包 spring-framework jar包的下载地址是:http://repo.spring.io/release/org/spring ...

  9. 开发人员的福音:微软、谷歌、Mozilla将他们所有的web API文档放在同一个地方

    Tips 原文作者:Liam Tung  原文地址:Developers rejoice: Microsoft, Google, Mozilla are putting all their web A ...

随机推荐

  1. Travis CI Build Continuous Integration

    什么是持续集成 持续集成(Continuous Integration)是经常合并小的代码更改的实践,而不是在开发周期结束时合并大的更改.目的是通过以较小的增量开发和测试来构建更健康的软件.这就是Tr ...

  2. 台电X16pro刷机记录

    Android: 如果要刷安卓,需要使用win7系统电脑,且需要安装java环境,同时按住 音量减+电源键进入刷机模式(DNX BOOT MODE..),这时在PhoneFlashTool_5.3.2 ...

  3. 17,a:img的alt和title有何异同? b:strong与en的异同?

    alt(alt text):为不能显示的图像,窗体或者applets的用户代理,alt属性用来指定替换文字.替换文字的语言用lang属性来指定. eg:下例中将图像作为链接来使用 <a href ...

  4. oracle错误代码大全(超详细)

    本篇文章是对oracle错误代码进行了详细的总结与分析,需要的朋友参考下 ORA-00001: 违反唯一约束条件 (.)ORA-00017: 请求会话以设置跟踪事件ORA-00018: 超出最大会话数 ...

  5. 四级技能修炼NPC脚本参考

    [@main] #act CloseBigDialogBox #say \ \ <本服推出部分四级技能.升级四级技能很简单./SCOLOR=250>\ \ <只需要1个/SCOLOR ...

  6. Spring 事务管理的使用

    Spring提供了2种事务管理 编程式的 声明式的(重点):包括xml方式.注解方式(推荐) 基于转账的demo dao层 新建包com.chy.dao,包下新建接口AccountDao.实现类Acc ...

  7. 「CF815C」Karen and Supermarket

    传送门 Luogu 解题思路 树形背包. 设 \(f[i][j][0/1]\) 表示在以 \(i\) 为根的子树中选 \(j\) 件商品的最少花费. 边界条件: \(f[i][j][0] = \min ...

  8. php mongdb driver 1.17

    Installation To build and install the driver: $ pecl install mongodb $ echo "extension=mongodb. ...

  9. unittest---unittest错误截图

    在做自动化的过程中,大多数执行者都不在旁边,那么如果用例失败了我们通常看报告上的失败信息,但是这样有时候可能不够清楚的判断到底哪里出了错误,我们还可以通过自动截图的功能,判断用例走到哪里出了错误. 截 ...

  10. Mysql常用的sql语句

    替换某字段的字符串: UPDATE article SET content = replace(content, '解决', '解放') WHERE ID<5000; 清空数据库,id也置空: ...