1. 程式人生 > >【編輯器】unity自動化生成UI模板程式碼

【編輯器】unity自動化生成UI模板程式碼

前言

在遊戲製作用,UI的程式碼架構是固定的。為了快速開發,只需要獲得一個完整的UI結構程式碼,然後編寫對應的業務邏輯即可。所以,自動化生成模板程式碼是一件必不可少的事情。

環境

UI的架構通常使用MVC的結構,這次就演示V的生成,其他模板的生成流程其實也大同小異。程式碼就不加功能了,重點放到生成程式碼上面去。

思路

  1. 製作模板程式碼,設定標誌位。
  2. 生成->得到元件,遍歷模板,在標誌位後新增元件處理。
    更新->標誌位範圍的程式碼不儲存,重新生成元件程式碼。
  3. 根據指定生成路徑,生成程式碼。

View

public class TempletView 
{
public const string Name = "TempletView"; public GameObject m_GameObject = null; public Transform m_Transform = null; public void OnInit(GameObject root) { m_GameObject = root; m_Transform = m_GameObject.transform; InitUI(); } } private void
InitUI() { //Start //End }

建立程式碼

StringBuilder codeStringBuilder = new StringBuilder();

using(StreamReader reader  = File.OpenText(TempletViewPath)
{
      string lineReader = string.Empty;
      while ((lineReader = reader.ReadLine()) != null)
      {
      	 if(lineReader .Contains
("TempletView ") { lineReader = lineReader.replace("TempletView",prefabName); } codeStringBuilder. Append(lineReader); if(lineReader.Contains("Transform m_Transform") { for(int index = 0;index<Components.count;index++) { codeStringBuilder.Append($"m_{Components[index].name}_{Components[index].getType().Name} = null;\n"); } } if(lineReader.Contains("Start") { for(int index = 0;index<Components.count;index++) { codeStringBuilder.Append($"m_{Components[index].name}_{Components[index].getType().Name} = m_Transform.Find("{Components[index].name}").gameobject.GetComponent<{Components[index].getType().Name}>();\n"); } } } } if(codeStringBuilder.Length>0) { StreamWriter writter = File.CreateText(UIFilePath); writter.Write(codeStringBuilder.toString()); writter.Close(); }

更新程式碼

StringBuilder codeStringBuilder = new StringBuilder();

using(StreamReader reader  = File.OpenText(UIFilePath)
{
      string lineReader = string.Empty;      
      bool replace =false;
      while ((lineReader = reader.ReadLine()) != null)
      {
	if(!replace)
	{  
	       codeStringBuilder. Append(lineReader);
	}
  	if(lineReader.Contains("Start") || lineReader.Contains("Transform m_Transform"))
	{      
	       replace  = true;
	}  

	if(lineReader.Contains("void OnInit"))
	{
	       replace = false;
	       for(int index = 0;index<Components.count;index++)    
      	       {     
            	      codeStringBuilder.Append($"m_{Components[index].name}_{Components[index].getType().Name} =  null;\n");
               }               
               codeStringBuilder.Append("\n\n");
               codeStringBuilder.Append(lineReader);
         }
  
	if(lineReader.Contains("End")
  	{      
  	       replace  = false;
  	       for(int index = 0;index<Components.count;index++)    
  	       {     
     		      codeStringBuilder.Append($"m_{Components[index].name}_{Components[index].getType().Name} =  m_Transform.Find("{Components[index].name}").gameobject.GetComponent<{Components[index].getType().Name}>();");
               } 
	      codeStringBuilder.Append(lineReader);
	}
     }
 }

if(codeStringBuilder.Length>0)
{ 
 	StreamWriter writter = File.CreateText(UIFilePath);
 	writter.Write(codeStringBuilder.toString());
 	writter.Close();
}

注意點

  1. StreamWriter 打開了必須要關閉,否則該檔案一直會處於使用狀態。再執行就跑不了,只能重開UNITY。這也是為什麼我放到最後統一搞,這樣上面無論怎麼崩潰都不會影響寫入。
  2. File的使用要小心,看清楚是開啟還是複寫,否則異常中斷時,檔案內容可能就被清空了。。2.File的使用要小心,看清楚是開啟還是複寫,否則異常中斷時,檔案內容可能就被清空了。。
  3. 使用using名稱空間,可以控制StreamReader的使用範圍,免得被其他地方意外呼叫。
  4. 文件的更新需要依賴標誌,如例子中的“Start‘和‘End’。這個標誌需要是唯一的,而且不可被刪除,否則就更新不了了。