在日常开发中,我们经常遇到或者写出这样的代码

  1. var sTrAngeNamingVariable = "a variable";
  2. #if UNITY_IOS || UNITY_ANDROID || UNITY_EDITOR
  3. sTrAngeNamingVariable = "a!value";
  4. #else
  5. sTrAngeNamingVariable = "other value";
  6. #endif

宏本身没有什么问题。但是 MonoDevelop IDE 上,只要写了宏判断,后边的代码的排版就会出问题。这是第一点。

第二点是,当我们发现 sTrAngeNamingVariable 的命名很不规范的时候,要对此变量进行重命名。一般的 IDE 都会支持变量/类/方法的重命名。

借助 IDE 的重命名功能,代码会变成如下:

  1. var strangeVariableName = "a variable";
  2. #if UNITY_IOS || UNITY_ANDROID || UNITY_EDITOR
  3. strangeVariableName = "a!value";
  4. #else
  5. sTrAngeNamingVariable = "other value";
  6. #endif

else 代码块里的变量重命名没有成功。当宏判断散落在各处时,很难发现这种错误。直到打包/AssetBundle/切换平台时,问题才会暴露(笔者也是被坑了很多次T.T)。

从这里得出的结论 : 当进行重构时,宏相关的代码会对重构造成风险,也不利于维护。在这里笔者设计出了 Platform。首先看下怎么使用:

  1. var strangeVariableName = "a variable";
  2. if (Platform.IsiOS || Platform.IsAndroid || Platform.IsEditor)
  3. {
  4. sTrAngeNamingVariable = "a!value";
  5. }
  6. else
  7. {
  8. sTrAngeNamingVariable = "other value";
  9. }

代码很简单,就是把 宏 换成了 Platform 而已。

这时候我们再进行下重命名。重命名后代码如下:

  1. if (Platform.IsiOS || Platform.IsAndroid || Platform.IsEditor)
  2. {
  3. strangeNamingVariable = "a!value";
  4. }
  5. else
  6. {
  7. strangeNamingVariable = "other value";
  8. }

重命名问题解决了。

Platform 的代码很简单,贴出简单看下就可以了。

  1. namespace QFramework
  2. {
  3. public class Platform
  4. {
  5. public static bool IsAndroid
  6. {
  7. get
  8. {
  9. bool retValue = false;
  10. #if UNITY_ANDROID
  11. retValue = true;
  12. #endif
  13. return retValue;
  14. }
  15. }
  16. public static bool IsEditor
  17. {
  18. get
  19. {
  20. bool retValue = false;
  21. #if UNITY_EDITOR
  22. retValue = true;
  23. #endif
  24. return retValue;
  25. }
  26. }
  27. public static bool IsiOS
  28. {
  29. get
  30. {
  31. bool retValue = false;
  32. #if UNITY_IOS
  33. retValue = true;
  34. #endif
  35. return retValue;
  36. }
  37. }
  38. }
  39. }

只是简单的把宏封装了一下。

但是 Platform 不是万能的,有一些事项还是要注意一下。

  • 在有 Platform 的条件语句块里,不能使用平台特有的 API ,如果要使用这种 API 还是建议封装一下,平台特有的 API 或者 宏 最好不要出现在 UI 或者 逻辑层代码中。
  • Platform.cs 这个类不能打成 dll。
  • 其他的大家来补充:),目前上线了几个项目,都没什么问题。

当笔者在接手一个项目的时候,优先会把所有宏相关的判断,能换的全换成 Platform ,不能换的,比如使用了平台特有 API 的都会简单封装下,然后再进行一些小部分的重命名,以熟悉一些代码的逻辑。

有一些宏判断比较棘手,比如:

  1. if ("1" == "2" || "2" == "3")
  2. {
  3. // do sth
  4. #if UNITY_EDITOR
  5. }
  6. else
  7. {
  8. // do sth
  9. #else
  10. // do sth
  11. #endif
  12. }

如果遇到这种代码,

首先先揍一顿写这种代码的人吧。哈哈,开玩笑的。

体谅一下吧,也许是版本太急了,谁都不想写出这样的代码,都有苦衷,都不容易,最起码是没有 bug 的。

解决办法是有的,就是复制一遍代码。第一份代码删掉 # if 代码块的代码,把宏换成对应的 Platform API,第二份代码删掉 # else 代码块的代码,然后一样把宏换成对应的 Platform API。 剩下的就容易解决了。

17 年年底的时候看了 《重构》 这本书,这里还是推荐大家看一下吧,有点枯燥,但是收获很多。

Hard Code 是难免的,追求代码质量的道路是没有终点的,让代码产生价值才是我们游戏开发者要做的。

今天就到这里。

转载请注明地址:凉鞋的笔记:liangxiegame.com

更多内容

Unity 游戏框架搭建 (二十三) 重构小工具 Platform的更多相关文章

  1. Unity 游戏框架搭建 2019 (十三~十五) 接下来要学什么?& 第九个示例

    在之前的两篇中,我们使用 public 静态方法对之前的内容进行了一个抽取,有了 public 静态方法这个工具,我们的学习行为也发生了一点变化. 在没使用 public 关键字之前呢,每一个示例仅仅 ...

  2. Unity 游戏框架搭建 (二) 单例的模板

      上一篇文章中说到的manager of managers,其中每个manager都是单例的实现,当然也可以使用静态类实现,但是相比于静态类的实现,单例的实现更为通用,可以适用大多数情况. 如何设计 ...

  3. Unity 游戏框架搭建 (二十二) 简易引用计数器

    引用计数是一个很好用的技术概念,不要被这个名字吓到了.首先来讲讲引用计数是干嘛的. 引用计数使用场景 有一间黑色的屋子,里边有一盏灯.当第一个人进屋的时候灯会打开,之后的人进来则不用再次打开了,因为已 ...

  4. Unity 游戏框架搭建 (二十一) 使用对象池时的一些细节

    上篇文章使用SafeObjectPool实现了一个简单的Msg类.代码如下: class Msg : IPoolAble,IPoolType { #region IPoolAble 实现 public ...

  5. Unity 游戏框架搭建 (二十) 更安全的对象池

    上篇文章介绍了,只需通过实现IObjectFactory接口和继承Pool类,就可以很方便地实现一个SimpleObjectPool.SimpleObjectPool可以满足大部分的对象池的需求.而笔 ...

  6. Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)

    最近在看Unity官方的AssetBundle(以下简称AB)的教程,也照着做了一遍,不过做出来的AssetBundleManager的API设计得有些不太习惯.目前想到了一个可行的解决方案.AB相关 ...

  7. Unity 游戏框架搭建 (十三) 无需继承的单例的模板

    之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...

  8. Unity 游戏框架搭建 (十) QFramework v0.0.2小结

    从框架搭建系列的第一篇文章开始到现在有四个多月时间了,这段时间对自己来说有很多的收获,好多小伙伴和前辈不管是在评论区还是私下里给出的建议非常有参考性,在此先谢过各位. 说到是一篇小节,先列出框架的概要 ...

  9. Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介

    约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...

随机推荐

  1. 深入理解jQuery插件开发总结(二)

    1,开始 可以通过为jQuery.fn增加一个新的函数来编写jQuery插件.属性的名字就是你的插件的名字: jQuery.fn.myPlugin = function(){ //开始写你的代码吧! ...

  2. easyui window窗口 随body的滚动条 滚动

    问题描述: 当easyui window窗口弹出的时候,依然可以滚动body 的滚动条,而且window窗口也会随它一起滚动 思路:bootstrap 模态框弹出的时候,给body 添加了 .moda ...

  3. Java设计模式—原型模式

    原型设计模式是一种比较简单的设计模式,在项目中使用的场景非常多. 个人理解: 原型模式实现了对Java中某个对象的克隆功能,即该对象的类必须implements实现Cloneable接口来标识为可被克 ...

  4. 解决Maven 报 Return code is: 400 , ReasonPhrase:Repository version policy: SNAPSHOT does not allow version: 2.1.0.RELEASE. 的错误

    最近在搭建公司的基础框架,业务需求用到elasticsearch,所以需要整合到基础框架里,供各业务线使用同时也便于管理,但在整合的过程中,出现了莫名的问题,同时maven的提示也不够明确. 我的版本 ...

  5. Java 之 static的使用方法(6)

    Java 中的 static 使用之静态变量 大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立. 然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是  ...

  6. android应用js

    http://blog.csdn.net/carson_ho/article/details/64904691 通过 WebViewClient 的方法shouldOverrideUrlLoading ...

  7. SQL点点滴滴_DELETE小计

    惨痛的教训: 某次在执行delete时,一时疏忽忘记写where条件了, 1.删除tb_mobile_cust_micromsg中的内容,前提是c_customer这个字段的值与#datamod表中c ...

  8. ubuntu16.04下无法连接网络的bug

    首先介绍下Bug的情况,这个bug纠缠我整整一天,在命令行下ifconfig能够看到ip地址,不过我的不是eth0,而是enps03,然后Ping 本机和ping 网关都能够 ping 通,但是sud ...

  9. JavaScript返回上一页

    目前来说有两种方法: window.history.back(); // 返回上一页不刷新 window.location.href = document.referrer; // 返回上一页并刷新

  10. July 19th 2017 Week 29th Wednesday

    Rather than envy others, it is better to speed up their own pace. 与其羡慕他人,不如加快自己的脚步. The envy of othe ...