1. 程式人生 > >Unity 遊戲框架搭建 2019 (二十三、二十四) 備份與版本號&危險的操作

Unity 遊戲框架搭建 2019 (二十三、二十四) 備份與版本號&危險的操作

先列出上一篇的總結:

  1. 要做的事情:
    • 備份:匯出檔案,並取一個合理的名字。
  2. 遺留問題:
    • 第八個示例與之前的示例程式碼重複,功能重複。
  3. 約定和規則:
    • 每個示例在 QFramework 目錄下建立一個資料夾,資料夾的格式是: 數字.示例的功能
    • 每個示例寫一個指令碼,指令碼中包含可複用的靜態方法和 MenuItem 方法。
    • 每寫一個示例進行一次匯出,匯出的檔名後邊加上日期和時間,這個功能已經在匯出功能裡內建了。
  4. 示例分類:
    1. 知識學習&收集
      • API 收集
      • C# 語法實踐
    2. 庫本身的功能
      • 規則實現
      • 使用流程提供及優化
      • 效率提升(編碼體驗、邏輯複用)
      • 專案實用工具收集

我們先解決第一個問題,備份問題。

檔案命名

匯出檔案很容易,但是檔案的名字就比較有講究了。現在我們的庫呢第一次進行比較大的整理,未來說不定有很多次這樣的整理。所以檔案命名應該能夠體現庫的某一個階段。

我們目前的命名規是 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 了甚至更好,而本系列專欄的亮點就是這個。

到此呢,我們成功了。

不過以上程式碼呢,還存在一些問題:

  1. 方法所在的類名比較奇怪,比如 GenerateUnityPackageName 和 ExportPackage 所在的類都是 PreviousFunctions,PreviousFunctions 意思是之前的方法。是為了配合示例的名字而起的。

  2. 選單欄的顯示順序問題,目前選單欄的顯示順序有點混亂,如下。


這個問題存在了好久了,不過沒辦法,因為一到七個示例已經寫好了,當時沒辦法更改,在整理階段是改掉這個問題的比較好的時機。

因為在本篇文章的開頭,有說過我們一個一個示例進行整理,所以這兩個問題,我們先記錄下來,等每個示例都整理了一遍之後,再看看如何解決。

除了以上存在的這兩個問題,我們還做了一個比較危險的操作,就是先刪除了第六個示例,等到第七個示例的時候發現功能失效了,還好在第八個示例中我們有相同的功能實現,否則就要去靠記憶力去恢復功能了,或者靠我們 v0.0.0 版本的備份進行恢復。這樣會耗費我們額外的精力和時間,是很不值當的。

基於這個經驗,我們在整理程式碼的時候,要優先確保功能是有效的,然後再進行一些變更或者刪除的操作。

小結

把以上兩個問題記錄下來,我們的總結又可以更新了,更新後如下。

  1. 要做的事情:
    • (完成) 備份:匯出檔案,並取一個合理的名字。
  2. 遺留問題:
    • (完成一部分) 第八個示例與之前的示例程式碼重複,功能重複。
    • 方法所在類的命名有問題。
    • 選單欄顯示順序問題。
  3. 約定和規則:
    • 每個示例在 QFramework 目錄下建立一個資料夾,資料夾的格式是: 數字.示例的功能
    • 每個示例寫一個指令碼,指令碼中包含可複用的靜態方法和 MenuItem 方法。
    • 每寫一個示例進行一次匯出,匯出的檔名後邊加上日期和時間,這個功能已經在匯出功能裡內建了。
    • 每次有 API 變更的時候做一次備份,備份的名字採用 QFramework_vX.Y.Z 格式。
    • 每次進行整理的時候要確保是在功能有效的情況下進行刪除和變更。
  4. 示例分類:
    1. 知識學習&收集
      • API 收集
      • C# 語法實踐
    2. 庫本身的功能
      • 規則實現
      • 使用流程提供及優化
      • 效率提升(編碼體驗、邏輯複用)
      • 專案實用工具收集

除了更新了兩個問題以外,又在約定和規則中增加了關於備份的規則,描述得很清楚了,這裡不多說了。

今天的內容就這些,拜拜~

轉載請註明地址:涼鞋的筆記:liangxiegame.com

更多內容

  • QFramework 地址:https://github.com/liangxiegame/QFramework

  • QQ 交流群:623597263

  • Unity 進階小班:

    • 主要訓練內容:
      • 框架搭建訓練(第一年)
      • 跟著案例學 Shader(第一年)
      • 副業的孵化(第二年、第三年)
    • 權益、授課形式等具體詳情請檢視《小班產品手冊》:https://liangxiegame.com/master/intro
  • 關注公眾號:liangxiegame 獲取第一時間更新通知及更多的免費內容。