最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【Unity】工具類系列教程—— 代碼自動(dòng)化生成!

2017-12-14 17:55 作者:皮皮關(guān)做游戲  | 我要投稿

【為什么要做自動(dòng)化工具】

工具類的創(chuàng)建是為了解決實(shí)際問題或者優(yōu)化既有流程,我們來先看看一些項(xiàng)目里面經(jīng)常遇到的問題。

程序代碼有很多時(shí)候類是相似的,因此新建一個(gè)功能的時(shí)候你會(huì)直接復(fù)制了之前"相似"的代碼塊,然后刪除掉無用的邏輯功能,但是有時(shí)候會(huì)出現(xiàn)漏網(wǎng)之魚。


開完會(huì),策劃發(fā)過來一個(gè)功能案子,UI相關(guān)的界面非常的多,你費(fèi)勁拼完了UI,寫腳本類的時(shí)候?qū)⒛阌玫降囊恍┙M件一個(gè)一個(gè)寫了函數(shù)變量加進(jìn)腳本中去,有時(shí)候一運(yùn)行發(fā)現(xiàn)報(bào)錯(cuò),結(jié)果是有一個(gè)函數(shù)沒有賦值,要么是有一個(gè)按鈕沒有生成變量,創(chuàng)建到調(diào)試中間花費(fèi)大量時(shí)間精力。


功能做完了,按理來說你應(yīng)該放松下來喝一杯咖啡,但是你一更新發(fā)現(xiàn)UI預(yù)制體的紅色沖突警告心直接涼了半截,解決預(yù)制體沖突后,又一遍一遍的將丟失的引用賦值到腳本上。


如果計(jì)算機(jī)能幫我們直接創(chuàng)建一個(gè)功能的基礎(chǔ)腳本類,就不用每次去復(fù)制上次的代碼了。然后再幫我們把那些亂七八糟又?jǐn)?shù)不勝數(shù)的按鈕、文字、圖片組件都自動(dòng)生成在腳本里面,然后自己去關(guān)聯(lián)好引用,一下就能節(jié)省好多重復(fù)的活。


效果展示


【相關(guān)功能實(shí)現(xiàn)與解析】


完整的腳本:


using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;


public class AutoBuildTemplate
{
?? public static string UIClass =
@"using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
public class #類名# : MonoBehaviour
{
//auto
? public void Start()
{
#查找#
}
#成員#
}
";
}


public class AutoBuild
{

? [MenuItem("生成/創(chuàng)建或刷新界面")]
?? public static void BuildUIScript()
?? {

?????? var dicUIType = new Dictionary<string, string>();

?????? dicUIType.Add("Img", "Image");
?????? dicUIType.Add("Btn", "Button");
?????? dicUIType.Add("Txt", "Text");
?????? dicUIType.Add("Tran", "Transform");


?????? GameObject[] selectobjs = Selection.gameObjects;

?????? foreach (GameObject go in selectobjs)
?????? {
?????????? //選擇的物體
?????????? GameObject selectobj = go.transform.root.gameObject;

?????????? //物體的子物體
?????????? Transform[] _transforms = selectobj.GetComponentsInChildren<Transform>(true);

?????????? List<Transform> childList = new List<Transform>(_transforms);

?????????? //UI需要查詢的物體
?????????? var mainNode = from trans in childList where trans.name.Contains('_') && dicUIType.Keys.Contains(trans.name.Split('_')[0]) select trans;

?????????? var nodePathList = new Dictionary<string, string>();

?????????? //循環(huán)得到物體路徑
?????????? foreach (Transform node in mainNode)
?????????? {
?????????????? Transform tempNode = node;
?????????????? string nodePath = "/" + tempNode.name;

?????????????? while (tempNode != tempNode.root)
?????????????? {
?????????????????? tempNode = tempNode.parent;

?????????????????? int index = nodePath.IndexOf('/');

?????????????????? nodePath = nodePath.Insert(index, "/" + tempNode.name);
?????????????? }

?????????????? nodePathList.Add(node.name, nodePath);
?????????? }

?????????? //成員變量字符串
?????????? string memberstring = "";
?????????? //查詢代碼字符串
?????????? string loadedcontant = "";

?????????? foreach (Transform itemtran in mainNode)
?????????? {
?????????????? string typeStr = dicUIType[itemtran.name.Split('_')[0]];

?????????????? memberstring += "public " + typeStr + " " + itemtran.name + " = null;\r\n\t";

?????????????? loadedcontant += itemtran.name + " = " + "gameObject.transform.Find(\"" + nodePathList[itemtran.name] + "\").GetComponent<" + typeStr + ">();\r\n\t\t";
?????????? }


?????????? string scriptPath = Application.dataPath + "/Scripts/" + selectobj.name + ".cs";


?????????? string classStr = "";

?????????? //如果已經(jīng)存在了腳本,則只替換//auto下方的字符串
?????????? if (File.Exists(scriptPath))
?????????? {
?????????????? FileStream classfile = new FileStream(scriptPath, FileMode.Open);
?????????????? StreamReader read = new StreamReader(classfile);
?????????????? classStr = read.ReadToEnd();
?????????????? read.Close();
?????????????? classfile.Close();
?????????????? File.Delete(scriptPath);

?????????????? string splitStr = "//auto";
?????????????? string unchangeStr = Regex.Split(classStr, splitStr, RegexOptions.IgnoreCase)[0];
?????????????? string changeStr = Regex.Split(AutoBuildTemplate.UIClass, splitStr, RegexOptions.IgnoreCase)[1];

?????????????? StringBuilder build = new StringBuilder();
?????????????? build.Append(unchangeStr);
?????????????? build.Append(splitStr);
?????????????? build.Append(changeStr);
?????????????? classStr = build.ToString();
?????????? }
?????????? else
?????????? {
?????????????? classStr = AutoBuildTemplate.UIClass;
?????????? }

?????????? classStr = classStr.Replace("#類名#", selectobj.name);
?????????? classStr = classStr.Replace("#查找#", loadedcontant);
?????????? classStr = classStr.Replace("#成員#", memberstring);


?????????? FileStream file = new FileStream(scriptPath, FileMode.CreateNew);
?????????? StreamWriter fileW = new StreamWriter(file, System.Text.Encoding.UTF8);
?????????? fileW.Write(classStr);
?????????? fileW.Flush();
?????????? fileW.Close();
?????????? file.Close();


?????????? Debug.Log("創(chuàng)建腳本 " + Application.dataPath + "/Scripts/" + selectobj.name + ".cs 成功!");
?????????? AssetDatabase.SaveAssets();
?????????? AssetDatabase.Refresh();
?????? }
?? }

}


腳本解析:

AutoBuildTemplate類

Unity中的C#腳本代碼本質(zhì)上為包含字符串內(nèi)容的文本文件,以.cs后綴保存。因此我們?nèi)绻詣?dòng)生成腳本只用編輯好代碼的文本內(nèi)容,然后添加文件后綴保存文件就完成了。
我們替換其中的 #類名#、#查找#、#成員#,保存成xxx.cs的文件就可以生成一個(gè)腳本類出來。


AutoBuild類

GameObject[] selectobjs = Selection.gameObjects;
Unity中可以在Editor腳本調(diào)用Selection類得到當(dāng)前選中的物體。因?yàn)榇嬖诙噙x情況,返回的物體為一個(gè)數(shù)組。



??? var dicUIType = new Dictionary<string, string>();
??????
dicUIType.Add("Img", "Image");
??????
dicUIType.Add("Btn", "Button");
??????
dicUIType.Add("Txt", "Text");
??????
dicUIType.Add("Tran", "Transform");

外部按鈕、圖片、文本等組件物體的關(guān)鍵字與類型的映射,當(dāng)子物體中名字存在“Img”、“Btn”就識(shí)別為Image和Button。


var mainNode = from trans in childList where trans.name.Contains('_') && dicUIType.Keys.Contains(trans.name.Split('_')[0]) select trans;

Linq的from 、where ?、select 語句遍歷尋找出前綴存在字典映射中的物體。
/*查詢是一種從數(shù)據(jù)源檢索數(shù)據(jù)的表達(dá)式。 查詢通常用專門的查詢語言來表示。 隨著時(shí)間的推移,人們已經(jīng)為各種數(shù)據(jù)源開發(fā)了不同的語言;例如,用于關(guān)系數(shù)據(jù)庫的 SQL 和用于 XML 的 XQuery。 因此,開發(fā)人員對(duì)于他們必須支持的每種數(shù)據(jù)源或數(shù)據(jù)格式,都不得不學(xué)習(xí)一種新的查詢語言。 LINQ 通過提供一種跨各種數(shù)據(jù)源和數(shù)據(jù)格式使用數(shù)據(jù)的一致模型,簡(jiǎn)化了這一情況。 在 LINQ 查詢中,始終會(huì)用到對(duì)象。 可以使用相同的基本編碼模式來查詢和轉(zhuǎn)換 XML 文檔、SQL 數(shù)據(jù)庫、ADO.NET 數(shù)據(jù)集、.NET 集合中的數(shù)據(jù)以及對(duì)其有 LINQ 提供程序可用的任何其他格式的數(shù)據(jù)。
資料地址docs.microsoft.com/zh-c*/


string unchangeStr = Regex.Split(classStr, splitStr, RegexOptions.IgnoreCase)[0];

正則表達(dá)式去分割字符串,因?yàn)楫?dāng)腳本已經(jīng)存在,我們不能覆蓋掉已經(jīng)書寫的代碼,所以基礎(chǔ)文本中有一個(gè)//auto來分割自動(dòng)生成代碼區(qū)域和手寫區(qū)域。


classStr = classStr.Replace("#類名#", selectobj.name);

字符串替換功能,將基礎(chǔ)文本中的關(guān)鍵字替換。



? FileStream file = new FileStream(scriptPath, FileMode.CreateNew);
??????????
StreamWriter fileW = new StreamWriter(file, System.Text.Encoding.UTF8);
??????????
fileW.Write(classStr);
??????????
fileW.Flush();
??????????
fileW.Close();
??????????
file.Close();
AssetDatabase.SaveAssets();
??????????
AssetDatabase.Refresh();

創(chuàng)建流文件,當(dāng)寫入完成后關(guān)閉流。在Unity生成了物體必須調(diào)用 AssetDatabase.SaveAssets()和AssetDatabase.Refresh()才能即時(shí)的看到資源刷新。


【總結(jié)】

以上利用UI預(yù)制體代碼自動(dòng)生成為例講解了自動(dòng)化生成的方法,我這里是通過Find來查找物體引用的,當(dāng)然可以利用Unity序列化參數(shù)的方法來賦值(就是拖拽操作的賦值方法),用后者可以節(jié)約UI第一次打開的性能(畢竟Unity的Find還是很消耗性能的),可以在我們的腳本創(chuàng)建好后加入給預(yù)制體掛載腳本賦值的功能流程。

自動(dòng)化思想是偉大的,可以用到自動(dòng)化的地方還有很多,比如統(tǒng)計(jì)當(dāng)前的資源加載列表,將策劃的表文件生成類文件,生成版本控制腳本。


如果你對(duì)你的項(xiàng)目有改良性建議,你認(rèn)為可以而且應(yīng)該實(shí)現(xiàn)自動(dòng)化任務(wù),就可以嘗試去實(shí)現(xiàn),一旦你已經(jīng)成功了,節(jié)省的可不僅僅是開發(fā)的時(shí)間。

如果沒活不要作死




對(duì)游戲開發(fā)感興趣的同學(xué),歡迎圍觀我們:【皮皮關(guān)游戲開發(fā)教育】 ,會(huì)定期更新各種教程干貨,更有別具一格的線下小班教育。

我們的官網(wǎng)地址:http://www.levelpp.com/

我們的游戲開發(fā)技術(shù)交流群:610475807

我們的微信公眾號(hào):皮皮關(guān)


【Unity】工具類系列教程—— 代碼自動(dòng)化生成!的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
新河县| 苏尼特右旗| 电白县| 高阳县| 章丘市| 五峰| 吉木乃县| 衡水市| 临沭县| 忻城县| 芷江| 阳山县| 尚志市| 丹江口市| 玛曲县| 玉山县| 桐庐县| 平原县| 定兴县| 武功县| 嘉兴市| 苗栗县| 拉孜县| 江源县| 南华县| 合水县| 宁南县| 石屏县| 台南县| 佛坪县| 纳雍县| 柏乡县| 黔南| 麻阳| 洛宁县| 武鸣县| 新田县| 漠河县| 洪洞县| 景洪市| 思南县|