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

var sTrAngeNamingVariable = "a variable";

#if UNITY_IOS || UNITY_ANDROID || UNITY_EDITOR
sTrAngeNamingVariable = "a!value";
#else
sTrAngeNamingVariable = "other value";
#endif

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

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

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

var strangeVariableName = "a variable";

#if UNITY_IOS || UNITY_ANDROID || UNITY_EDITOR
strangeVariableName = "a!value";
#else
sTrAngeNamingVariable = "other value";
#endif

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

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

var strangeVariableName = "a variable";

if (Platform.IsiOS || Platform.IsAndroid || Platform.IsEditor)
{
sTrAngeNamingVariable = "a!value";
}
else
{
sTrAngeNamingVariable = "other value";
}

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

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

if (Platform.IsiOS || Platform.IsAndroid || Platform.IsEditor)
{
strangeNamingVariable = "a!value";
}
else
{
strangeNamingVariable = "other value";
}

重命名问题解决了。

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

namespace QFramework
{
public class Platform
{
public static bool IsAndroid
{
get
{
bool retValue = false;
#if UNITY_ANDROID
retValue = true;
#endif
return retValue;
}
} public static bool IsEditor
{
get
{
bool retValue = false;
#if UNITY_EDITOR
retValue = true;
#endif
return retValue;
}
} public static bool IsiOS
{
get
{
bool retValue = false;
#if UNITY_IOS
retValue = true;
#endif
return retValue;
}
}
}
}

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

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

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

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

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

if ("1" == "2" || "2" == "3")
{
// do sth
#if UNITY_EDITOR
}
else
{
// do sth
#else
// do sth
#endif
}

如果遇到这种代码,

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

体谅一下吧,也许是版本太急了,谁都不想写出这样的代码,都有苦衷,都不容易,最起码是没有 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. [翻译]Review——The Inner Workings Of Virtual DOM

    The Inner Workings Of Virtual DOM 虚拟DOM的内部工作机制 原文地址:https://medium.com/@rajaraodv/the-inner-workings ...

  2. Ubuntu 下 /etc/resolv.conf文件总是自动清除问题的解决方案

    最近学习Linux,在虚拟机中安装的是Ubuntu操作系统,用了几天发现Ubuntu无法上网,打开命令终端,输入命令: ping www.baidu.com -c2 结果显示名称无法识别,而直接与宿主 ...

  3. 花1台的钱入手2台【最能抗DDoS】阿里云主机【攻略】

    花1台的钱入手2台[最能抗DDoS]阿里云主机[攻略]: 第一步:先申请0元半年 http://click.aliyun.com/m/335/:注:0元机器只有新帐号可申请第二步:再买6折37/月 h ...

  4. Python爬虫教程-31-创建 Scrapy 爬虫框架项目

    本篇是介绍在 Anaconda 环境下,创建 Scrapy 爬虫框架项目的步骤,且介绍比较详细 Python爬虫教程-31-创建 Scrapy 爬虫框架项目 首先说一下,本篇是在 Anaconda 环 ...

  5. 使用C++11实现完美资源管理

    1.资源管理包括内存管理.文件句柄等等需要进行打开(申请).关闭(释放)操作的过程 2.VS2010使用的C++规范,严格说来不是C++11,而是C++0x,但是一脉相承的 一:管理数组 相较于aut ...

  6. 我要为运维说一句,我们不是网管,好不!!Are you know?

    运维 运维,这里指互联网运维,通常属于技术部门,与研发.测试.系统管理同为互联网产品技术支撑的4大部门,这个划分在国内和国外以及大小公司间都会多少有一些不同. 一个互联网产品的生成一般经历的过程是:产 ...

  7. Oracle案例03——RMAN-06091: no channel allocated for maintenance (of an appropriate type)

    同事收到告警磁盘空间不足,说删除归档无法直接在rman中进行操作,让帮看下,具体处理方法如下: 一.错误信息 在rman执行命令 crosscheck archivelog all; delete n ...

  8. 【Leetcode】【Medium】Binary Tree Inorder Traversal

    Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...

  9. php集群和分布式理解

    首先架构层次来说: php的集群是指很多台服务器处理同样的工作,指的是硬件上的一般,比如slb负载均衡主要作用是有多台服务器处理同样的工作, php分布式是指多台服务器处理不同的工作,指的是业务上的一 ...

  10. HDU 3420 -- Bus Fair ACM

    Bus Fair Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...