最近的工作跟 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. txt文件太大打不开怎么办

    #开始 最近在调试代码的时候,生成了一个400MB的日志文件 找了很多文本编辑器,都表示太大了打不开 QAQ #解决方案 百度下载 “txt杀手” 用这个软件把文本文件拆分成小份就可以打开了 输入如图 ...

  2. 解决linux 运行自动化脚本浏览器无法启动问题

    1.前提你的驱动和版本对应无问题时,依旧报未知错误无法启动chrome 解决方法加上两行: options.addArguments("no-sandbox");options.a ...

  3. 【笔记6-支付及订单模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    支付模块 实际开发工作中经常会遇见如下场景,一个支付模块,一个订单模块,有一定依赖,一个同事负责支付模块,另一个同事负责订单模块,但是开发支付模块的时候要依赖订单模块的相关类 ,方法,或者工具类,这些 ...

  4. jq基础(2)

    jquery的选择器 基本选择器 id选择器:$(“#id名称”); 元素选择器:$(“元素名称”); 类选择器:$(“.类名”); 通配符:* 多个选择器共用(并集) 案例代码: <html& ...

  5. POJ1087 A Plug of UNIX

    你作为某高管去住宿了,然后宾馆里有几种插座,分别有其对应型号,你携带了几种用电器(手机,电脑一类的),也有其对应型号:可是不一定用电器就能和插座匹配上,于是宾馆的商店里提供了一些转换器,这些转换器可以 ...

  6. ZOJ4109 Welcome Party(2019浙江省赛)

    并查集算连通块的数量,集合的个数就是必然不开心的人数,再跑bfs,用优先队列维护~ #include<bits/stdc++.h> using namespace std; ; vecto ...

  7. 无数据库模式kong/kong-ingress-controller

    apiVersion: v1kind: Namespacemetadata:  name: kong---apiVersion: apiextensions.k8s.io/v1beta1kind: C ...

  8. nyoj 11

    水题... #include <stdio.h> #include <algorithm> #include <iostream> int main() { int ...

  9. JShell的使用

    JShell脚本工具是JDK9的新特性 启动JShell工具,在DOS命令行直接输入JShell命令.(如下例) 这里我们用Hello,World举例: 结果显示是正确的. 这里再举一个例子: 结果可 ...

  10. Java的下载与安装

    下载Java 如果要是想聊天,那我们就需要腾讯QQ,先把它下载过来安装上,就可以聊天了,那如果是想要开发java程序呢,我们就需要下载一个开发工具包“jdk”,安装上就可以开发了.当然java是属于哪 ...