技術筆記(10)Unity編輯器擴充套件

静候霜白發表於2024-03-16

技術筆記(10)Unity編輯器擴充套件

  • 希望實現的功能或目標:

    • 編寫一個編輯器擴充套件功能,用以快速建立Event和Command指令碼

  • 學習筆記:

    • CreateScriptWindow類

      • 繼承EditorWindow類

      • 用兩個常量字串,記錄模板所在的檔案路徑

        • const string EVENTTEMPLATE_PATH = "Assets/Scripts/GameFramework/ReusableCode/Layers/Utility/Editor/EventTemplateScript.txt";
          const string COMMANDTEMPLATE_PATH = "Assets/Scripts/GameFramework/ReusableCode/Layers/Utility/Editor/CommandTemplateScript.txt";
          
      • 呼叫MenuItem選擇新增按鈕的索引位置

        • [MenuItem("Assets/Create/C# Event Script(Command)")]
      • AssetsCreate方法:呼叫GetWindow方法,得到一個當前類名的window,並呼叫這個window的Show方法

        •     static void AssetsCreate()
              {
                  CreateScriptWindow window = (CreateScriptWindow)GetWindow(typeof(CreateScriptWindow), false, "建立C#");
                  window.Show(true);
              }
          
      • 兩個普通字串

        •     string _scriptName;
              string _description;
          
      • OnGUI方法

        • 透過GetPath方法獲取當前所選的目錄

        • 在Directory中查詢該目錄是否存在

          • 如果存在,則建立一個TextField用來輸入指令碼名。

            • 然後建立一個“建立事件”按鈕

            • 如果建立成功了,設定要生成的指令碼的路徑,並展示出來

              • 檢測輸入的指令碼名是否正確,是否已有同名指令碼並報錯
              • 如果都沒問題,把模板裡的內容讀出來,把所有的“My”替換成輸入的指令碼名,並以UTF8的編碼格式寫到新生成的指令碼里
              • 重新整理project列表,顯示建立成功的提示資訊
          • 建立命令指令碼的邏輯同上

        •     private void OnGUI()
              {
                  string selectDirPath = GetPath();
                  if (Directory.Exists(selectDirPath))
                  {
                      _scriptName = EditorGUILayout.TextField("指令碼名:", _scriptName);
          
                      if(GUILayout.Button("建立事件", GUILayout.Height(40)))
                      {
                          string path = selectDirPath + "/" + _scriptName + "Event.cs";
                          EditorGUILayout.LabelField("路徑:", path);
                          EditorGUILayout.Space();
                          if (!CheckScriptName(_scriptName))
                          {
                              ShowNotification(new GUIContent("請輸入正確的指令碼名!"));
                          }
                          else if(CheckRepeat(selectDirPath))
                          {
                              ShowNotification(new GUIContent("當前資料夾下已經有同名指令碼!"));
                          }
                          else
                          {
                              string content = File.ReadAllText(EVENTTEMPLATE_PATH);
                              content = content.Replace("My", _scriptName);
                              File.WriteAllText(path, content, Encoding.UTF8);
                              AssetDatabase.Refresh();
                              ShowNotification(new GUIContent("Success!"));
                          }
                      }
          
                      if (GUILayout.Button("建立命令", GUILayout.Height(40)))
                      {
                          string path = selectDirPath + "/" + _scriptName + "Command.cs";
                          EditorGUILayout.LabelField("路徑:", path);
                          EditorGUILayout.Space();
                          if (!CheckScriptName(_scriptName))
                          {
                              ShowNotification(new GUIContent("請輸入正確的指令碼名!"));
                          }
                          else if (CheckRepeat(selectDirPath))
                          {
                              ShowNotification(new GUIContent("當前資料夾下已經有同名指令碼!"));
                          }
                          else
                          {
                              string content = File.ReadAllText(COMMANDTEMPLATE_PATH);
                              content = content.Replace("My", _scriptName);
                              File.WriteAllText(path, content, Encoding.UTF8);
                              AssetDatabase.Refresh();
                              ShowNotification(new GUIContent("Success!"));
                          }
                      }
                  }
                  else
                  {
                      EditorGUILayout.LabelField("請在Project皮膚中選擇將要放置指令碼的資料夾");
                  }
          
              }
          
      • CheckScriptName方法

        • 用正規表示式記錄命名標準格式
        • 對輸入的引數進行檢測,並返回是否符合格式
        •     bool CheckScriptName(string scriptName)
              {
                  Regex regex = new Regex("^[a-zA-Z_][a-zA-Z0-9_]*$");
                  return regex.IsMatch(scriptName);
              }
          
      • CheckRepeat方法

        • 以所選路徑為引數,new一個DirectoryInfo物件
        • 並用FileInfo陣列存這個DirectoryInfo物件裡獲取到的所有檔案
        • 指令碼名字串附上其格式“.cs”
        • 遍歷FileInfo陣列,與檔名一一進行對比,有重名則返回true,無則返回false
        •     bool CheckRepeat(string selectDirPath)
              {
                  DirectoryInfo dir = new DirectoryInfo(selectDirPath);
                  FileInfo[] files = dir.GetFiles();
                  string scriptName = _scriptName + ".cs";
                  for(int i = 0;i<files.Length;i++)
                  {
                      if (files[i].Name == scriptName)
                      {
                          return true;
                      }
                  }
                  return false;
              }
          
      • OnSelectionChange方法

        • 呼叫Repaint方法
      • GetPath方法

        • 呼叫AssetDatabase類的GetAssetPath方法,以Selection.activeInstanceID作為其引數。從而獲得選中資產的相對路徑
        •     private string GetPath()
              {
                  string assetPath = null;
                  if(assetPath == null || assetPath == "")
                  {
                      assetPath = AssetDatabase.GetAssetPath(Selection.activeInstanceID);
                  }
                  return assetPath;
              }
          

  • 實現過程中產生的疑惑:

    • 編輯器擴充套件的作用?
    • 有哪些實際的應用?

  • 對疑惑的解答:

    • 其允許我們透過自定義指令碼和外掛來增強和個性化unity編輯器的功能,主要作用有:

      • 提高開發效率:自動化處理重複性任務
      • 自定義工具和介面:以適應特定的開發需求,提高工作流程和效率和舒適度
      • 增強視覺化編輯:繪製輔助圖形、直觀編輯物件屬性
      • 整合第三方工具:3d建模、音影片編輯軟體
    • 實際應用:

      • 可用來執行遊戲特定部分,進行快速測試而無需啟動整個遊戲
      • 查詢和替換材質、最佳化紋理等
      • 整合Photoshop、Blender等外部工具的功能

日期:

相關文章