Unity 遊戲框架搭建 2019 (二十三、二十四) 備份與版本號&危險的操作
先列出上一篇的總結:
- 要做的事情:
- 備份:匯出檔案,並取一個合理的名字。
- 遺留問題:
- 第八個示例與之前的示例程式碼重複,功能重複。
- 約定和規則:
- 每個示例在 QFramework 目錄下建立一個資料夾,資料夾的格式是: 數字.示例的功能
- 每個示例寫一個指令碼,指令碼中包含可複用的靜態方法和 MenuItem 方法。
- 每寫一個示例進行一次匯出,匯出的檔名後邊加上日期和時間,這個功能已經在匯出功能裡內建了。
- 示例分類:
- 知識學習&收集
- API 收集
- C# 語法實踐
- 庫本身的功能
- 規則實現
- 使用流程提供及優化
- 效率提升(編碼體驗、邏輯複用)
- 專案實用工具收集
- 知識學習&收集
我們先解決第一個問題,備份問題。
檔案命名
匯出檔案很容易,但是檔案的名字就比較有講究了。現在我們的庫呢第一次進行比較大的整理,未來說不定有很多次這樣的整理。所以檔案命名應該能夠體現庫的某一個階段。
我們目前的命名規是 QFramework_日期_時,這種命名能夠體現庫的某個時間點,從而我們能夠在多個檔案之間找到最後一次更新的庫。但是這樣還不夠。如果現在想找到第一篇文章的庫,那要去找到第一篇文章寫的時間。找到這個庫的難度會隨著時間越來越困難。不過這種命名已經完成了它的使命,最起碼從第一個示例到現在沒出現太大的問題。
但是有新的要求了。因為示例的程式碼會被刪除,這算是程式碼的比較大的變更了,而且看專欄的童鞋所在的階段也不同,有的童鞋剛剛看第一篇而有的童鞋已經完結了。所以要考慮庫的各個階段。
如何表示庫的某個階段呢?
有一種比較好的方式,就是按照文章的標題命名,比如這篇文章之前的庫名字為 QFramework_19_開始整理,或者按照最新的示例名字,比如 QFramwork_13 GameObject 顯示、隱藏簡化。但是這樣的名字過了很久回過頭來找檔案還是會要凌亂好一會,所以並不合適。
比較合適的是用版本號,我們生活中使用的軟體都有版本號,比如 Unity 5.6.5 或者 2017.2 等等。對於開發者來說版本號已經是比較熟悉的東西了。
使用版本號命名的檔案格式為: QFramework_vX.Y.Z
X 是主版本號,用於不向前相容的更新。
Y 是中間版本,用於可向前相容的功能性更新。
Z 是小版本號,用於功能完善和 bug 修復的更新。
一般都是從 v0.1.1 這個版本開始釋出的,但是這個版本呢叫做 mvp 版本,也就是最小可驗證版本。我們的庫還沒有到這個階段,而且版本號這個東西剛開始用,是用於方便自己記憶的,也是為了做一個備份而已,還不用釋出給別人用。所以我們的備份版本為 v0.0.0 。
還有一點要注意的是,v0.x.y 這個階段的版本可以不考慮向前相容。但是如果已經 v0.1.1 了,就要釋出出去了,也有使用者在使用了,那就要儘可能要做到向前相容。
向前相容的意思是,使用者升級版本不必更改 API 的使用。
開始備份
在上一小節得到了結論。
現在,我們要開始著手匯出。使用匯出工具匯出檔案,並手動把檔名字命名為 QFramework_v0.0.0。
這樣備份就算完成了。
可以把它放到網盤或者硬盤裡。這樣就可以安心整理程式碼了。
小結
版本號算是約定和規則的內容。
危險的操作
今天開始,進行逐個示例的整理。
第一個示例
先看第一個。
#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"));
}
}
}
因為在第八個示例裡給提取成方法了,所以這個示例可以直接刪除了。
刪除之後的檔案結構如下圖所示。
第二個示例
程式碼如下
#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 = "要複製的關鍵字";
}
}
}
這個也在第八個示例中提取成方法了,所以這部分也可以直接刪了,
刪除之後的檔案結構如下圖所示:
第三個示例
程式碼如下:
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");
}
}
}
這個示例是是原來示例一和示例二的結合,同樣在第八個示例中提取成方法了,果斷刪。
第四個示例
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
}
}
同理,果斷刪。
第五個示例
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
}
}
同理,果斷刪。
第六個示例
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
}
}
同理果斷刪
第七個示例
#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
}
}
第七個示例是快捷鍵功能,不過我們沒有在第八個示例中提取成方法,因為快捷鍵不可以複用。
而這個是我們目前匯出功能的核心程式碼,所以比較重要,這個就不能刪除了。
通過觀察可知,MenuClicked 方法中的對 MenuItem "QFramework/6.MenuItem 複用" 的複用,已經失效了,因為第六個示例被我們刪掉了。
不過沒關係,我們在第八個示例中有提取成方法。而使用方法完成匯出功能的程式碼如下:
[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");
}
不過在寫第八個示例的時候還是在用 MenuItem 進行方法的呼叫,雖然那時候已經學習了呼叫 public 方法,但是由於 public 方法的運用沒有那麼純熟,想不到是很正常的。但是現在不一樣了,我們用 public 方法進行非常多的方法設計練習了,所以直接著手整理就好了。
整理後的第七個示例程式碼如下:
using System.IO;
#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()
{
var generatePackageName = PreviousFunctions.GenerateUnityPackageName();
PreviousFunctions.ExportPackage("Assets/QFramework",generatePackageName + ".unitypackage");
PreviousFunctions.OpenInFolder(Path.Combine(Application.dataPath, "../"));
}
#endif
}
}
這些方法都是自己實現的,呼叫起來比較親切了吧?
等待編譯之後,再按下快捷鍵 ctrl/cmd + e,就自動匯出成功了,感受到滿滿的成就感。
不過命名方式還是 QFramework_日期_時,不過沒關係,這不算真正的匯出,只是測試而已,我們還沒有整理結束。整理這個階段雖然在文章中要寫很久,但是實際過程中可能幾分鐘就整理完了。但是整理這個過程寫文章很久的原因是,因為在整理的候筆者的內心戲份非常多,也就是思考經過會非常多。而筆者呢都要把它們展示出來,這樣大家理解了這些,就不難自己再造個 QFramework 了甚至更好,而本系列專欄的亮點就是這個。
到此呢,我們成功了。
不過以上程式碼呢,還存在一些問題:
-
方法所在的類名比較奇怪,比如 GenerateUnityPackageName 和 ExportPackage 所在的類都是 PreviousFunctions,PreviousFunctions 意思是之前的方法。是為了配合示例的名字而起的。
-
選單欄的顯示順序問題,目前選單欄的顯示順序有點混亂,如下。
這個問題存在了好久了,不過沒辦法,因為一到七個示例已經寫好了,當時沒辦法更改,在整理階段是改掉這個問題的比較好的時機。
因為在本篇文章的開頭,有說過我們一個一個示例進行整理,所以這兩個問題,我們先記錄下來,等每個示例都整理了一遍之後,再看看如何解決。
除了以上存在的這兩個問題,我們還做了一個比較危險的操作,就是先刪除了第六個示例,等到第七個示例的時候發現功能失效了,還好在第八個示例中我們有相同的功能實現,否則就要去靠記憶力去恢復功能了,或者靠我們 v0.0.0 版本的備份進行恢復。這樣會耗費我們額外的精力和時間,是很不值當的。
基於這個經驗,我們在整理程式碼的時候,要優先確保功能是有效的,然後再進行一些變更或者刪除的操作。
小結
把以上兩個問題記錄下來,我們的總結又可以更新了,更新後如下。
- 要做的事情:
- (完成) 備份:匯出檔案,並取一個合理的名字。
- 遺留問題:
- (完成一部分) 第八個示例與之前的示例程式碼重複,功能重複。
- 方法所在類的命名有問題。
- 選單欄顯示順序問題。
- 約定和規則:
- 每個示例在 QFramework 目錄下建立一個資料夾,資料夾的格式是: 數字.示例的功能
- 每個示例寫一個指令碼,指令碼中包含可複用的靜態方法和 MenuItem 方法。
- 每寫一個示例進行一次匯出,匯出的檔名後邊加上日期和時間,這個功能已經在匯出功能裡內建了。
- 每次有 API 變更的時候做一次備份,備份的名字採用 QFramework_vX.Y.Z 格式。
- 每次進行整理的時候要確保是在功能有效的情況下進行刪除和變更。
- 示例分類:
- 知識學習&收集
- API 收集
- C# 語法實踐
- 庫本身的功能
- 規則實現
- 使用流程提供及優化
- 效率提升(編碼體驗、邏輯複用)
- 專案實用工具收集
- 知識學習&收集
除了更新了兩個問題以外,又在約定和規則中增加了關於備份的規則,描述得很清楚了,這裡不多說了。
今天的內容就這些,拜拜~
轉載請註明地址:涼鞋的筆記:liangxiegame.com
更多內容
-
QFramework 地址:https://github.com/liangxiegame/QFramework
-
QQ 交流群:623597263
-
Unity 進階小班:
- 主要訓練內容:
- 框架搭建訓練(第一年)
- 跟著案例學 Shader(第一年)
- 副業的孵化(第二年、第三年)
- 權益、授課形式等具體詳情請檢視《小班產品手冊》:https://liangxiegame.com/master/intro
- 主要訓練內容:
-
關注公眾號:liangxiegame 獲取第一時間更新通知及更多的免費內容。