第一章小结

为了强化教程的重点,会在合适的时候进行总结与快速复习。

第二章 简介

在第一章我们做了知识库的准备,从而让我们更高效地收集示例。

在第二章,我们就用准备好的导出工具试着收集几个示例,这些示例中有的是我们后续库的基础工具,也有的是在项目中非常实用的小工具,还有一些示例是实践了在框架搭建方向上非常重要的 C# 语法知识。

第二章大纲如下。

第八个示例(一)

在之前,我们完成了一个导出的功能。但是在完成这个功能的过程中,我们也遇到了一些问题。我们回忆一下,在《MenuItem 复用》的这篇文章中,我们想对如下代码进行复用。

using System;
#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class ExportUnityPackage : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/4.导出 UnityPackage")]
private static void MenuClicked()
{
var assetPathName = "Assets/QFramework";
var fileName = "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh") + ".unitypackage";
AssetDatabase.ExportPackage(assetPathName, fileName, ExportPackageOptions.Recurse);
}
#endif
}
}

这个方法被声明为 private 权限,所以是不可以被访问的。不过还好,MenuItem 可以复用,问题就勉强解决了。但是每次复用的时候要手打或复制一遍字符串未免也太麻烦了,而且也容易出错。那么还有其他的方式么?

这就是今天要解决的问题。当别的示例想调用以上的方法的时候,由于是 private 类型,所以只能通过 MenuItem 的方式进行调用,而 MenuItem 这种方式比较麻烦。

解决方案大家很容易就想到,把 private 改成 public 就行了。这样从达成代码复用这个目的的这个角度来说,问题是算是解决了,但是以笔者的经验来讲,这样还会有一些问题,就到这样就好。我们好好享受这个胜利的果实。

到这里如果有不知道 private 和 public 关键字的作用是什么的童鞋,那么笔者就简单提一句,使用 private 定义的方法只能在类的内部或者内部类中被调用,则不可以被子类和外部类调用,而使用 public 定义的方法,如果所在类也是 public 类型的,那么在任意地方可以被调用。

我们要怎么用这个 public 关键字呢?是在写示例的时候,仅仅把 private 改成 public 就行了嘛?有没有更好用的方法?

如果仅仅是把 private 改成 public 不是最好的方法,因为通过 MenuItem 修饰的方法,不能传参数,也没有返回值。不能传参或不能返回值的话,一个方法的使用就会受限。

所以笔者给出的方案是,再创建一个静态的 public 方法,而这个方法被 MenuItem 调用。这样的好处是,我们在创建一个方法的时候,可以好好地利用参数和返回值进行设计。

说了这么多,终于得到了一个明确的方案。我们来通过今天的第八个示例快速试一下。

第八个示例

第八个示例是什么呢,就是在第八个示例中,把所有的示例都提取成方法,并再次完成导出的功能。

首先第一个示例代码如下:

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine;
using System; namespace QFramework
{
public static class LogFileName
{
#if UNITY_EDITOR
[MenuItem("QFramework/1.生成 unitypackage 名字")]
#endif
private static void GenerateUnityPackageName()
{
Debug.Log("QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh"));
}
}
}

这个示例的核心是 DateTime.Now.ToString() 这个代码。之所以是核心,是因为没用过它的人,第一次用会感觉很陌生,而且 Unity 和 C# 的 API 有那么多,怎么可能一个一个全部记住呢?所以就写了这样的一个示例,以便日后,要用的时候迅速翻阅这个代码就可以知道怎么用。随着时间,这个 API 用的次数会越来越多,慢慢自己就记住了。但是就算记住了,也有可能会忘的那一天,所以还有得让它在我们的库中存在。

OK,我们直接看提取后的代码。

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine;
using System; namespace QFramework
{
public class PreviousFunctions : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/1.获取文件名")]
#endif
private static void MenuClicked()
{
Debug.Log(GenerateUnityPackageName());
} public static string GenerateUnityPackageName()
{
return "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh");
}
}
}

首先注意,MenuItem,由于第八个示例是有很多的东西,所以就又加了一级菜单。

点击以上菜单,执行结果正确。

第八个示例(二)

在上一篇我们抽取了第一个示例的方法,我们在这篇在接着往下抽取。

提取第二个示例

先看第二个示例的代码。

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public static class CopyText2Clipboard
{
#if UNITY_EDITOR
[MenuItem("QFramework/2.复制文本到剪切板")]
#endif
private static void CopyText()
{
GUIUtility.systemCopyBuffer = "要复制的关键字";
}
}
}

核心 API 是 GUIUtility.systemCopyBuffer,而后边的内容,应该是使用的时候自己填的。所以要创建一个 string 类型的参数,用来接收要复制的内容。抽取后的方法如下。

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/2.复制文本到剪切板")]
#endif
private static void MenuClicked2()
{
CopyText("要复制的关键字");
} public static void CopyText(string text)
{
GUIUtility.systemCopyBuffer = text;
}

提取第三示例

我们接着看第三个示例

using System;
#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class GenerateUnityPackageName2ClipBoard
{
#if UNITY_EDITOR
[MenuItem("QFramework/3.生成文件名到剪切板")]
#endif
private static void MenuClicked()
{
GUIUtility.systemCopyBuffer = "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh");
}
}
}

第三个示例和第一个和第二个示例重复了所以没有抽取的必要。不过,我们还是要实现与第三个 MenuItem 同等的功能的。

代码如下:

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/3.生成文件名到剪切板")]
#endif
private static void MenuClicked3()
{
CopyText(GenerateUnityPackageName());
}

提取第四示例

第四个示例代码如下:

using System;
#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class ExportUnityPackage : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/4.导出 UnityPackage")]
private static void MenuClicked()
{
var assetPathName = "Assets/QFramework";
var fileName = "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh") + ".unitypackage";
AssetDatabase.ExportPackage(assetPathName, fileName, ExportPackageOptions.Recurse);
}
#endif
}
}

核心是 AssetDatabase.ExportPackage 这个 API。一般情况下 ExportPackageOptions 都是用 Recurse。所以只声明两个参数就好了。一个是 assetPathNam,一个是 fileName。抽取后的方法如下。

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage")]
private static void MenuClicked4()
{
ExportPackage("Assets/QFramework",GenerateUnityPackageName() + ".unitypackage");
}
#endif public static void ExportPackage(string assetPathName,string fileName)
{
#if UNITY_EDITOR
AssetDatabase.ExportPackage(assetPathName, fileName, ExportPackageOptions.Recurse);
#endif
}

提取第五个示例

首先看代码:

using System;
#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class OpenInFolder
{
#if UNITY_EDITOR
[MenuItem("QFramework/5.打开所在文件夹")]
private static void MenuClicked()
{
Application.OpenURL("file:///" + Application.dataPath);
}
#endif
}
}

核心的 API 就是 OpenURL,在打开文件夹的时候,一般路径的前缀是固定的。提取成如下:

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/5.打开所在文件夹")]
private static void MenuClicked5()
{
OpenInFolder(Application.dataPath);
}
#endif
public static void OpenInFolder(string folderPath)
{
Application.OpenURL("file:///" + folderPath); }

提取第六个示例

先看代码

using System.IO;
#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class ReuseMenuItem : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/6.MenuItem 复用")]
private static void MenuClicked()
{
EditorApplication.ExecuteMenuItem("QFramework/4.导出 UnityPackage");
Application.OpenURL("file:///" + Path.Combine(Application.dataPath, "../"));
}
#endif
}
}

核心 API 是 EditorApplication.ExecuteMenuItem。

提取方法后的代码如下。

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/6.MenuItem 复用")]
private static void MenuClicked6()
{
CallMenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage");
OpenInFolder(Path.Combine(Application.dataPath, "../"));
} public static void CallMenuItem(string menuPath)
{
EditorApplication.ExecuteMenuItem(menuPath);
}
#endif

提取第七个示例

先看代码:

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine; namespace QFramework
{
public class CustomShortCut : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/7.自定义快捷键 %e")]
private static void MenuClicked()
{
EditorApplication.ExecuteMenuItem("QFramework/6.MenuItem 复用");
}
#endif
}
}

这个呢是自定义快捷键,所以目前没有办法复用,只能记在代码里了。在这里我们直接输出一句话就好。

代码如下:

#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/7.自定义快捷键")]
private static void MenuClicked7()
{
Debug.Log("%e 意思是快捷键 cmd/ctrl + e");
}
#endif

到此呢,第八个示例的代码算写完了。

如下:

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine;
using System;
using System.IO; namespace QFramework
{
public class PreviousFunctions : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/1.获取文件名")]
#endif
private static void MenuClicked()
{
Debug.Log(GenerateUnityPackageName());
} public static string GenerateUnityPackageName()
{
return "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh");
} #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/2.复制文本到剪切板")]
#endif
private static void MenuClicked2()
{
CopyText("要复制的关键字");
} public static void CopyText(string text)
{
GUIUtility.systemCopyBuffer = text;
} #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/3.生成文件名到剪切板")]
#endif
private static void MenuClicked3()
{
CopyText(GenerateUnityPackageName());
} #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage")]
private static void MenuClicked4()
{
ExportPackage("Assets/QFramework",GenerateUnityPackageName() + ".unitypackage");
}
#endif public static void ExportPackage(string assetPathName,string fileName)
{
#if UNITY_EDITOR
AssetDatabase.ExportPackage(assetPathName, fileName, ExportPackageOptions.Recurse);
#endif
} #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/5.打开所在文件夹")]
private static void MenuClicked5()
{
OpenInFolder(Application.dataPath);
}
#endif
public static void OpenInFolder(string folderPath)
{
Application.OpenURL("file:///" + folderPath);
} #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/6.MenuItem 复用")]
private static void MenuClicked6()
{
CallMenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage");
OpenInFolder(Path.Combine(Application.dataPath, "../"));
} public static void CallMenuItem(string menuPath)
{
EditorApplication.ExecuteMenuItem(menuPath);
}
#endif #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/7.自定义快捷键")]
private static void MenuClicked7()
{
Debug.Log("%e 意思是快捷键 cmd/ctrl + e");
}
#endif }
}

代码有点辣眼睛,因为宏定义太多了,并且 MenuItem 方法和 public 方法交叉使用,所以我们整理一下,整理后的代码如下。

#if UNITY_EDITOR
using UnityEditor;
#endif using UnityEngine;
using System;
using System.IO; namespace QFramework
{
public class PreviousFunctions : MonoBehaviour
{
public static string GenerateUnityPackageName()
{
return "QFramework_" + DateTime.Now.ToString("yyyyMMdd_hh");
} public static void CopyText(string text)
{
GUIUtility.systemCopyBuffer = text;
} public static void CallMenuItem(string menuPath)
{
EditorApplication.ExecuteMenuItem(menuPath);
} public static void OpenInFolder(string folderPath)
{
Application.OpenURL("file:///" + folderPath);
} #if UNITY_EDITOR
public static void ExportPackage(string assetPathName,string fileName)
{
AssetDatabase.ExportPackage(assetPathName, fileName, ExportPackageOptions.Recurse);
}
#endif #if UNITY_EDITOR
[MenuItem("QFramework/8.总结之前的方法/1.获取文件名")]
private static void MenuClicked()
{
Debug.Log(GenerateUnityPackageName());
} [MenuItem("QFramework/8.总结之前的方法/2.复制文本到剪切板")]
private static void MenuClicked2()
{
CopyText("要复制的关键字");
} [MenuItem("QFramework/8.总结之前的方法/3.生成文件名到剪切板")]
private static void MenuClicked3()
{
CopyText(GenerateUnityPackageName());
} [MenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage")]
private static void MenuClicked4()
{
ExportPackage("Assets/QFramework",GenerateUnityPackageName() + ".unitypackage");
} [MenuItem("QFramework/8.总结之前的方法/5.打开所在文件夹")]
private static void MenuClicked5()
{
OpenInFolder(Application.dataPath);
} [MenuItem("QFramework/8.总结之前的方法/6.MenuItem 复用")]
private static void MenuClicked6()
{
CallMenuItem("QFramework/8.总结之前的方法/4.导出 UnityPackage");
OpenInFolder(Path.Combine(Application.dataPath, "../"));
} [MenuItem("QFramework/8.总结之前的方法/7.自定义快捷键")]
private static void MenuClicked7()
{
Debug.Log("%e 意思是快捷键 cmd/ctrl + e");
}
#endif
}
}

逐个执行菜单,运行结果全部正确。

到此呢,我们可以进行一次导出了。

ok,今天的内容就这些。

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

更多内容

Unity 游戏框架搭建 2019 (九~十二) 第一章小结&第二章简介&第八个示例的更多相关文章

  1. Unity 游戏框架搭建 2019 (四十二、四十三) MonoBehaviour 简化 & 定时功能

    MonoBehaviour 简化 在前两篇,我们完成了第九个示例.为了完善第九个示例,我们复习了类的继承,又学习了泛型和 params 关键字. 我们已经接触了类的继承了.接触继承之前,把类仅仅当做是 ...

  2. Unity 游戏框架搭建 2019 (三十二、三十三) 类的命名 & 代码文件命名

    昨天我们完成了第八个示例的第二个 MenuItem 菜单顺序的调整. 我们今天再往下接着调整. 我们来看下接下来的 MenuItem 代码如下: [MenuItem("QFramework/ ...

  3. Unity 游戏框架搭建 2019 (五十二~五十四) 什么是库?&第四章总结&第五章简介

    在上一篇,我们对框架和架构进行了一点探讨.我们在这一篇再接着探讨. 什么是库呢? 来自同一位大神的解释: 库, 插到 既有 架构 中, 补充 特定 功能. 很形象,库就是搞这个的.我们的库最初存在的目 ...

  4. # Unity 游戏框架搭建 2019 (三十四、三十五) 9 ~ 10 示例整理

    第九个示例 目前代码如下: using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace QFramework { p ...

  5. Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装

    MonoBehaviourSimplify 中的消息策略完善 在上一篇,笔者说,MonoBehaviourSimplify 中的消息策略还有一些小问题.我们在这篇试着解决一下. 先贴出来代码: usi ...

  6. Unity 游戏框架搭建 2019 (三十九、四十一) 第四章 简介&方法的结构重复问题&泛型:结构复用利器

    第四章 简介 方法的结构重复问题 我们在上一篇正式整理完毕,从这一篇开始,我们要再次进入学习收集示例阶段了. 那么我们学什么呢?当然是学习设计工具,也就是在上篇中提到的关键知识点.这些关键知识点,大部 ...

  7. Unity 游戏框架搭建 2019 (四十六) 简易消息机制 & 集成到 MonoBehaviourSimplify 里

    在上一篇,我们接触了单例,使用单例解决了我们脚本之间访问的问题. 脚本之间访问其实有更好的方式. 我们先分下脚本访问脚本的几种形式. 第一种,A GameObject 是 B GameObject 的 ...

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

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

  9. Unity 游戏框架搭建 2019 (五十、五十一) 消息机制小结&MonoBehaviourSimplify 是框架?

    我们花了 5 篇文章学习了消息机制的方方面面.并且完成了一个简易消息机制,之后集成到了我们的 MonoBehaviourSimplify 里. 现在 MonoBehaviourSimplify 有一点 ...

随机推荐

  1. 自然语言分析工具Hanlp依存文法分析python使用总结(附带依存关系英文简写的中文解释)

    最近在做一个应用依存文法分析来提取文本中各种关系的词语的任务.例如:text=‘新中国在马克思的思想和恩格斯的理论阔步向前’: 我需要提取这个text中的并列的两个关系,从文中分析可知,“马克思的思想 ...

  2. ERROR 1129 (00000) Host ‘XXXXXX’ is blocked because of many connection errors; unblock with ‘mysqlad

    1.今天早上由于公司网络带宽达到上限,导致多台web服务器连接mysql服务器超时.后来情况好转后,连接数据库服务器出现如下错误. Host '*' is blocked because of man ...

  3. Linux Command Backup

    User Structure linux command review 列出所有信号 找到名字后,kill 或者用ps找到 kill同名进程 每隔一秒高亮显示网络链接数的变化情况 启动关闭制定网卡 关 ...

  4. 为什么我们要让人工智能玩游戏:微软Project AIX

    <我的世界>游戏 2016年7月注:Project AIX已正式更名为Project Malmo 注:本文编译自Project AIX: Using Minecraft to build ...

  5. 什么是SNAT

    SNAT是源地址转换,其作用是将ip数据包的源地址转换成另外一个地址,可能有人觉得奇怪,好好的为什么要进行ip地址转换啊,为了弄懂这个问题,我们要看一下局域网用户上公网的原理,假设内网主机A(192. ...

  6. 在GitHub上分享自己的项目

    GitHub主要是用作基于Git的分布式版本管理系统的库,可以保存和管理自己的代码,而且主要用作代码的合作开发. 注册GitHub后你就会有0.3G的免费空间,不过只能创建公开项目,这也满足代码分享的 ...

  7. Microsoft Translator:消除面对面交流的语言障碍

    ​ Translator:消除面对面交流的语言障碍" title="Microsoft Translator:消除面对面交流的语言障碍"> ​ James Simm ...

  8. GIT 使用(二):创建仓库并提交代码

    基本操作 所用命令使用 windows 下安装 git-bash 运行 Table of Contents 先决条件 已经安装了 GIT 客户端 已经设置用户信息 如果没做可以看安装和配置 获取 Gi ...

  9. 差分放大电路的CMRR与输入电阻分析

    分析了经典差分放大电路的共模抑制比CMRR与输入电阻RIN 1.经典差分放大电路 基于运放的经典差分放大电路在各模电教材中均能找到,利用分离电阻和运算放大器实现,如图1所示为一种差分放大电路: 图1 ...

  10. 使用SpringMVC实现文件上传和下载

    文件上传 第一步,加入jar包: commons-fileupload-1.3.1.jar commons-io-2.4.jar 第二步,在SpringMVC配置文件中配置CommonsMultipa ...