Unity-自动生成代码(C#)

写代码(尤其是UI部分)时经常需要填写路径来查找需要操作的物体:
Transform btn = transform.Find("AAA\bbb\ccc");
以及通过Resource或Asset加载资源:
GameObject go = Resources.Load<GameObject>("UI/Prefab/CardList/CardListItem");
这样的重复工作很多而且容易写错路径,最好能通过鼠标选择需要查找的场景中物体或者资源,直接生成相关代码,包括路径定义、物体变量定义、物体查找、组件获取、注册事件、查找资源等代码。用VS开发WindowForm程序,其设计工具就可以直接生成相关代码,因为直接操作文件比较担心出错时会覆盖掉某些已有代码,功能写起来也麻烦,要写一整套检查工具。这里搞个简化版,生成代码后直接复制到剪贴板中,手动到需要的地方粘贴一下,虽然比WindowForm要Low一万倍,但简洁方便代码少,实际用起来效果也还行。

using System.IO;
using UnityEngine;
using UnityEditor;

/// <summary>
/// 查找物体或资源的路径,生成代码
/// @Author:      DidYouSeeMyBug
/// @CreateTime:  2018/7/2  17:58
/// @Desc:        可生成代码:声明并查找场景中物体,查找组件,添加组件事件,声明并查找项目资源  
/// </summary>
public class FindEditor : MonoBehaviour
{
    [MenuItem("TOOL/FindCode &F")]
    public static void FindCode()
    {
        string code = string.Empty;
        string resPath = "Assets/Resources/";
        string[] btnStr = {"Btn", "btn"};
        string[] groupStr = {"Group", "group"};

        // 选择资源
        UnityEngine.Object[] arr = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets);
        if (null != arr && 0 != arr.Length)
        {
            string definePathCode = string.Empty;
            string definePrefCode = string.Empty;
            string findCode = string.Empty;
            for (int i = 0; i < arr.Length; i++)
            {
                UnityEngine.Object obj = arr[i];
                string assetPath = AssetDatabase.GetAssetPath(obj);
                if (assetPath.StartsWith(resPath))
                {
                    string ext = Path.GetExtension(assetPath);
                    int pathLength = assetPath.Length - resPath.Length - ext.Length;
                    assetPath = assetPath.Substring(resPath.Length, pathLength);
                    string name = obj.name.Replace(" ", string.Empty);     
                    string pathStr = string.Format("path_{0}", name);
                    string prefabStr = string.Format("{0}_{1}",  ext.Substring(1), name);
                    string type = obj.GetType().Name;
                    definePathCode = string.Format("{0}private const string {1} = \"{2}\";\r\n", definePathCode,
                        pathStr, assetPath);
                    definePrefCode = string.Format("{0}private {1} {2};\r\n", definePrefCode, type, prefabStr);
                    findCode = string.Format("{0}{1} = Resources.Load<{2}>({3});\r\n", findCode, prefabStr, type,
                        pathStr);
                }
            }

            code = string.Format("{0}\r\n{1}\r\n{2}", definePathCode, definePrefCode, findCode);
        }
        else
        {
            // 选择场景
            string defineCode = string.Empty;
            string findCode = string.Empty;
            string addCallbackCode = string.Empty;
            string callbackCode = string.Empty;
            for (int i = 0; i < Selection.transforms.Length; i++)
            {
                var selecTransform = Selection.transforms[i];
                string name = selecTransform.name;
                string path = string.Empty;
                while (null != selecTransform)
                {
                    path = string.Format("{0}/{1}", selecTransform.name, path);
                    selecTransform = selecTransform.parent;
                }

                if (StartWithStrs(ref name, ref groupStr))
                {
                    Debug.Log("Group...");
                }
                if (StartWithStrs(ref name, ref btnStr))
                {
                    Debug.Log("Find Btn");
                    defineCode = string.Format("{0}\tButton {1}; \r\n", defineCode, name);

                    string TransName = string.Format("{0}Transform", name);

                    string transCode = string.Format("Transform {0} = transform.Find(\"{1}\"); ", TransName, path);
                    string componentCode = string.Format("\r\nif (null != {0})\r\n\t{1}\r\n\t\t{2} = {0}.GetComponent<Button>();\r\n\t{3}\r\n",
                        TransName, "{", name, "}");
                    findCode = string.Format("{0}\t{1}{2}", findCode, transCode, componentCode);
                    addCallbackCode =
                        string.Format("{0}\tif (null != {1})\r\n{2}\r\n\t{1}.onClick.AddListener(On{1});\r\n\t{3}\r\n",
                            addCallbackCode, name, "{", "}");
                    callbackCode = string.Format("{0}\tpublic void On{1}(){2}{3}\r\n", callbackCode, name, "{", "}");
                }
                else
                {
                    defineCode = string.Format("{0}\tTransform {1}; \r\n", defineCode, name);
                    findCode = string.Format("{0}\t{1} = transform.Find(\"{2}\"); \r\n", findCode, name, path);
                }
            }

            code = string.Format("{0}\r\n{1}\r\n{2}\r\n{3}", defineCode, findCode, addCallbackCode, callbackCode);
        }

        GUIUtility.systemCopyBuffer = code;
        Debug.Log("Found!");
    }

    /// <summary>
    /// 是否以数组中的字符串开头
    /// </summary>
    /// <param name="str">目标字符串</param>
    /// <param name="strs">检测字符串</param>
    /// <returns></returns>
    static bool StartWithStrs(ref string str, ref string[] strs)
    {
        for (int i = 0; i < strs.Length; i++)
        {
            if (str.StartsWith(strs[i]))
            {
                return true;
            }
        }

        return false;
    }
    
}


使用时直接选择需要的物体或者资源,ALT+F,即可生成代码。

可以根据需求修改Editor代码,更改生成代码的格式,样式,增加更多事件的支持等,还可以做一些其他处理,比如上面的代码在根据查找物名称生成变量名的时候会剔除空格,还可以在路径名前面加上@等等。

最开始这一套东西是我在做ulua工作的时候写的,所以也是Lua版本,查找物体生成Lua代码,那个版本的功能更多一些,还支持成组的物体,等下有空我再发一版Lua的。

以下为自动生成的代码,感觉格式和命名都很统一的代码看起来会很顺眼

// 资源路径
private const string path_BerserkerStrikeLV1 = "CardSprites/BerserkerStrikeLV1";
private const string path_CardChioce = "UI/Prefab/PopWindow/CardChioce";
private const string path_FloraAnimController = "Animator/FloraAnimController";
private const string path_CardDetail = "UI/Prefab/PopWindow/CardDetail";
private const string path_MainAudioMixer = "AudioMixer/MainAudioMixer";

// 资源
private Texture2D png_BerserkerStrikeLV1;
private GameObject prefab_CardChioce;
private AnimatorController controller_FloraAnimController;
private GameObject prefab_CardDetail;
private AudioMixerController mixer_MainAudioMixer;

// 场景物体
Button BtnAwards; 
Button BtnCards; 
Button BtnMonsters; 
Button BtnClose; 
Transform TabGroup; 

// 加载资源
png_BerserkerStrikeLV1 = Resources.Load<Texture2D>(path_BerserkerStrikeLV1);
prefab_CardChioce = Resources.Load<GameObject>(path_CardChioce);
controller_FloraAnimController = Resources.Load<AnimatorController>(path_FloraAnimController);
prefab_CardDetail = Resources.Load<GameObject>(path_CardDetail);
mixer_MainAudioMixer = Resources.Load<AudioMixerController>(path_MainAudioMixer);

// 查找物体
Transform BtnAwardsTransform = transform.Find("UIAchievementBook/UIAchievementBook/BG/BtnAwards/"); 
if (null != BtnAwardsTransform)
{
BtnAwards = BtnAwardsTransform.GetComponent<Button>();
}
Transform BtnCardsTransform = transform.Find("UIAchievementBook/UIAchievementBook/BG/BtnCards/"); 
if (null != BtnCardsTransform)
{
BtnCards = BtnCardsTransform.GetComponent<Button>();
}
Transform BtnMonstersTransform = transform.Find("UIAchievementBook/UIAchievementBook/BG/BtnMonsters/"); 
if (null != BtnMonstersTransform)
{
BtnMonsters = BtnMonstersTransform.GetComponent<Button>();
}
Transform BtnCloseTransform = transform.Find("UIAchievementBook/UIAchievementBook/CardBook(Clone)/BtnClose/"); 
if (null != BtnCloseTransform)
{
BtnClose = BtnCloseTransform.GetComponent<Button>();
}
TabGroup = transform.Find("UIAchievementBook/UIAchievementBook/CardBook(Clone)/TabGroup/"); 

// 添加事件
if (null != BtnAwards)
{
BtnAwards.onClick.AddListener(OnBtnAwards);
}
if (null != BtnCards)
{
BtnCards.onClick.AddListener(OnBtnCards);
}
if (null != BtnMonsters)
{
BtnMonsters.onClick.AddListener(OnBtnMonsters);
}
if (null != BtnClose)
{
BtnClose.onClick.AddListener(OnBtnClose);
}

// 声明函数
public void OnBtnAwards()
{

}
public void OnBtnCards()
{

}
public void OnBtnMonsters()
{

}
public void OnBtnClose()
{

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容