最近的工作跟 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. 如何在应用程序中使用ML.NET?

    https://www.cnblogs.com/shanyou/p/9190701.html ML.NET以NuGet包的形式提供,可以轻松安装到新的或现有的.NET应用程序中. 该框架采用了用于其他 ...

  2. 超长干货丨Kubernetes网络快速入门完全指南

    Kubernetes网络一直是一个非常复杂的主题.本文将介绍Kubernetes实际如何创建网络以及如何为Kubernetes集群设置网络. 本文不包括如何设置Kubernetes集群.这篇文章中的所 ...

  3. Java JDBC 数据库链接小结随笔

    Java JDBC 数据库链接小结随笔 一.链接数据库的步骤 二.关于Statement  和  PrepareStatement 两者区别 用法 三.关于 ResultSet 的一些小结 四.自定义 ...

  4. springboot~Transactional注解的注意事项

    @Transactional注解是为方法添加事务块的意思,使用aop的技术动态为方法添加事务范围,在使用它时可以在类或者方法上添加,但在类上添加时需要注意一下影响的范围. 类中添加Transactio ...

  5. K8S的安装

    两种方式安装k8s: 传统方式,使用二进制. 优点:能够让我们更清楚k8s的组件关系,可扩展性强,可定制化 缺点:不利于新手部署 使用kubeadm安装 优点:简单,高效 缺点:所有的事情都被kude ...

  6. 【原】jenkins知识点_凭据(一)

    一:凭据 1.目的: 与第三方网站或应用程序进行交互,如代码仓库.云存储系统和服务等 2.操作路径: Jenkins-凭据-系统-全局凭据 3.权限 Jenkins 中保存的凭证可以用于: 任何适用于 ...

  7. 查看服务器CPU相关信息!

    # 查看物理CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l # 查看每个物理CPU中core的个数(即 ...

  8. Tensorflow机器学习入门——AttributeError: module 'scipy.misc' has no attribute 'toimage'

    这个bug的解决办法: import cv2 # scipy.misc.toimage(image_array).save('cifar10_data/raw/%d.jpg' % i) cv2.imw ...

  9. 最全Pycharm教程(39)——Pycharm版本控制之本地Git用法

    1.主题 介绍如果通过Pycharm使用本地Git集. 2.准备工作 (1)PyCharm版本为2.7或更高 (2)已经创建一个工程 (3)Git插件可用,对应可执行文件在 Git page页面正确配 ...

  10. UITextField的快速基本使用代码块

    概述 UITextField在界面中显示可编辑文本区域的对象. 您可以使用文本字段来使用屏幕键盘从用户收集基于文本的输入.键盘可以配置许多不同类型的输入,如纯文本,电子邮件,数字等等.文本字段使用目标 ...