Unity 遊戲框架搭建 2019 (三十六~三十八) partial與public

在上一篇,我們把菜單的順序從頭到尾整理了一遍。在整理菜單順序的過程中,記錄了一個要做的事情。

要做的事情:

  • (完成) 備份:導出文件,並取一個合理的名字。
  • 整理完菜單順序後,學習新的知識,解決隨着示例增多,可能出現類需要合併的問題。

我們要學習新的知識,試着解決類的合併問題。首先我們來看下要合併的類是什麼,在我們的示例中是 TransformSimplify,這個 TransformSimplify 是對 Transform API 的簡化,而 Transform 有非常多的 API,那麼以後肯定還是會給 TransformSimplify 添加方法的。

而我們的示例是逐個寫的,寫了一個示例,發現要給 TransformSimplify 添加方法,再回頭找 TransformSimplify 類,再更改,這樣很不妥。因為如果更改了 TransformSimplify 這個類了,那麼對應的此篇專欄的文章就會失效了。

所以如果有一個方法能夠解決這個問題就好了,在每個示例就可以為已經有的類添加方法,而不去動用以前的示例代碼,等學習到一個階段後進行整理的時候統一進行合併。有這樣的東西嘛?

有的,C# 有提供 partial 關鍵字。

它可以讓一個類在多個文件中實現。那我們就試着給 TransformSimplify 和 GameObject 應用 partial 關鍵字吧。

TransformSimplify 在第五個示例,增加後的代碼如下:

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
#endif

namespace QFramework
{
	public partial class TransformSimplify
	{
#if UNITY_EDITOR
		[MenuItem("QFramework/5.Transform API 簡化/1.賦值優化", false, 5)]
#endif
		private static void MenuClicked1()
		{
			var transform = new GameObject("transform").transform;

			SetLocalPosX(transform, 5.0f);
			SetLocalPosY(transform, 5.0f);
			SetLocalPosZ(transform, 5.0f);
		}
		
#if UNITY_EDITOR
		[MenuItem("QFramework/5.Transform API 簡化/2.重置", false, 6)]
#endif
		private static void MenuClicked2()
		{
			var transform = new GameObject("transform").transform;

			Identity(transform);
		}

		/// <summary>
		/// 重置操作
		/// </summary>
		/// <param name="trans">Trans.</param>
		public static void Identity(Transform trans)
		{
			trans.localPosition = Vector3.zero;
			trans.localScale = Vector3.one;
			trans.localRotation = Quaternion.identity;
		}
		
		public static void SetLocalPosX(Transform transform, float x)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosY(Transform transform, float y)
		{
			var localPos = transform.localPosition;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosZ(Transform transform, float z)
		{
			var localPos = transform.localPosition;
			localPos.z = z;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosXY(Transform transform, float x, float y)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosXZ(Transform transform, float x, float z)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.z = z;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosYZ(Transform transform, float y, float z)
		{
			var localPos = transform.localPosition;
			localPos.y = y;
			localPos.z = z;
			transform.localPosition = localPos;
		}
	}
}

GameObjectSimplify 在第七個示例,增加 partial 之後代碼如下:

#if UNITY_EDITOR
using UnityEditor;
#endif
 
using UnityEngine;

namespace QFramework
{
    public partial class GameObjectSimplify
    {
        public static void Show(GameObject gameObj)
        {
            gameObj.SetActive(true);
        }

        public static void Hide(GameObject gameObj)
        {
            gameObj.SetActive(false);
        }

#if UNITY_EDITOR
        [MenuItem("QFramework/7.GameObejct API 簡化/顯示、隱藏簡化", false, 8)]
#endif
        private static void MenuClicked()
        {
            var gameObject = new GameObject();

            Hide(gameObject);
        }
    }
}

增加之後呢,我們添加一個示例,用來驗證 partial 關鍵字是否正確的。

新的示例呢,是第八個示例。

在示例中,分別為 TransformSimplify 和 GameObjectSimplify 增加一個方法。

代碼如下:

#if UNITY_EDITOR
using UnityEditor;
#endif
 
using UnityEngine;


namespace QFramework
{
    public partial class TransformSimplify
    {
        public static void AddChild(Transform transform, Transform childTrans)
        {
            childTrans.SetParent(transform);
        }
    }

    public partial class GameObjectSimplify
    {
        public static void Show(Transform transform)
        {
            transform.gameObject.SetActive(true);
        }

        public static void Hide(Transform transform)
        {
            transform.gameObject.SetActive(false);
        }
    }
    
    public class PartialKeyword
    {
#if UNITY_EDITOR
        [MenuItem("QFramework/8.partial 關鍵字", false, 9)]
#endif
        private static void MenuClicked()
        {
            var parentTrans = new GameObject("Parent").transform;
            var childTrans = new GameObject("Child").transform;
            
            TransformSimplify.AddChild(parentTrans,childTrans);
            GameObjectSimplify.Hide(childTrans);

        }
    }
}

執行的結果如下:006tNc79gy1fzfrjlpmilj30hw06c0sz.jpg

菜單如下:
006tNc79gy1fzfrjojvenj308f05bgnc.jpg

目錄如下:
006tNc79gy1fzfrjrd85tj30gm0agjss.jpg

學了這個 partial 之後,我們的合併問題就解決了。

這樣我們整理階段要做的事情就做完了。

要做的事情:

  • (完成) 備份:導出文件,並取一個合理的名字。
  • (完成) 整理完菜單順序後,學習新的知識,解決隨着示例增多,可能出現類需要合併的問題。

partial 和 public 的合理使用以及整理完結篇

在上一篇中,我們學習了新的知識 partial 關鍵字,那麼我們什麼時候該用 partial 呢?

我們簡單分析一下:

  • 像 GameObjectSimplify 和 TransformSimplify 都是很可能增長的類,所以自然就要用到了。
  • 而我們的 CommonUtil、EditorUtil、MathUtil 也是非常大的一個範疇,隨着時間,要加的東西也會越來越多的。所以這兩個類也要加上 partial。
  • 而 ResolutionCheck 類,目前只完成了比較常用的分辨率,未來隨着時間肯定會遇到比較奇葩的分辨率的。所以 ResolutionCheck 也要加上 partial。
  • Exporter 呢,是專門為導出功能定製的,目前比較完善了。所以用不到 partial。而且 Exporter 里的 GeneratePackageName 事實上也不需要被其他的類調用了,所以它的訪問權限也可以從 public 關鍵字也可以改成 private 了。

基於以上,我們要給除了 Exporter 以外的所有的類都加上 partial,然後要把第一個示例的 Exporter.GeneratePackageName 的 public 關鍵字改成 private。

到此呢,我們的整理就算真正的結束了。

整理之後我們得到了幾個類

  1. 簡化類:GameObjectSimplify、TransformSimplify
  2. Util 類:CommonUtil、EditorUtil、MathUtil、ResolutionCheck
  3. 編輯器功能:Exporter

這已經可以構成一個代碼庫了。

復盤

我們大體回憶下我們從第一篇到現在經歷的階段,大致可以分為如下兩個階段

  1. 學習收集示例階段。
  2. 整理階段。

學習收集示例階段

其實我們可以理解為做項目或者做功能,為了做項目呢,往往我們會積累下來大量的代碼。從而導致項目慢慢趨於混亂,直到無法在寫下去(比如筆者也是寫到某個示例的時候呢已經是瓶頸了,不知道寫什麼。

整理階段

在整理階段,會處理掉好多項目時間緊的時候沒時間解決的代碼設計問題。然後在整理階段呢,也還會遇到很多意外的問題。不過經過整理之後,項目的結構會更加合理精簡,再未來的一段時間內,可以讓開發者愉快滴寫功能,並且項目的發展也有了個方向(筆者也是通過這次整理,才知道了接下來的方向)。

知識庫 到 代碼庫

而我們的知識庫,一開始只是一個一個示例。而示例本身的存在,只是為了記錄我們所接觸的知識。但是隨着我們的示例增加以及經驗的提高,我們對示例庫的要求就會變高,從只是為了記錄知識到方法可復用、類名要合理。慢慢地就會變成一個代碼庫。

那麼大家還記得我們在第一篇定的小目標嘛? 打造自己的知識庫,結果打造着打造着變成了個代碼庫。當然代碼庫本身還是有記錄知識的作用的,只不過在記錄知識的作用上還能提高我們的編碼效率。之所以會這樣是因為程序語言本身的存在就是為了提高人類生產力(編碼效率),和傳達信息的(記錄知識)。

提高編碼效率,是因為它能夠復用,能夠記錄知識的原因是,本身程序語言就是傳達信息的,要不,它怎麼叫語言呢?

我們可以用日常用的語言寫筆記,但是用程序語言一樣也可以寫筆記,同樣筆記也是需要整理的。

從知識庫到代碼庫,我們也遇到了很多關鍵知識點,如下:

  1. public 關鍵字
  2. 類的第一作用
  3. partial 關鍵字

在接觸了這些關鍵知識點後,庫的結構就會發生革命性的變化,結構會變得更合理清晰,且更容易擴展。而這些關鍵知識點,目前大多來自於 C# 語法,但是它們不僅僅是語法知識,而是能夠幫助我們進行代碼設計的知識,筆者把這些知識叫做設計工具。

在代碼中不管是設計一個龐大系統還是給一個項目做架構,或者僅僅是設計一個方法,都離不開這些設計工具,有了這些,可以讓結構有更多地選擇,更多地可能性。

再次起航

通過這次整理,我們收穫了很多法寶,有了這些法寶我們有信心可以在接下來學習階段中克服一切困難。如果實在克服不了,大不了我們再進行一次整理。

說到整理,我們的庫開發流程已經算是成型了。很簡單,流程如下:

  • 學習收集示例
  • 整理
  • 學習收集示例
  • 整理
  • 學習收集示例

如此往複,很快我們就能造出一個 QFramework,只不過要再多接觸幾個設計工具(C# 關鍵知識)。

導出

到此呢,我們的整理就真正完結了。我們好久沒有進行導出了,在這篇我們就要進行一次導出,這次導出呢,要加上版本號。

版本號為 v0.0.1 ,所以導出的文件名應該是 QFramework_v0.0.1。

現在我們手頭應該有兩個版本的文件.

  • QFramework_v0.0.0: 整理之前的備份版本。
  • QFremework_v0.0.1: 整理完結後的版本。

第三章 小與快速複習

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

更多內容