Calmer的文章

  • 首页
  • 文章归档
  • 关于页面

  • 搜索
体验游戏 笔记 推荐 工具链 工具使用 小游戏 插件 UI 软件 教程

Unity3D Editor扩展(快速生成自己的UI代码)

发表于 2020-04-22 | 分类于 游戏开发 | 0 | 阅读次数 1371

前言

本文针对使用Unity3D UGUI进行UI开发所遇到的痛点。

  • 痛点:
    在使用UGUI进行UI开发时,我们往往需要查找相关UI物件的引用,然后保存起来重复使用;
    虽然简单,但是如果UI结构比较复杂了之后,每次都要去挨个生成变量,然后对应路径找其引用,若其中一不小心还容易输出一两个字母,费时又费力。
  • 解决:
    开发一个小工具,针对我们自己所需的代码模版,可以快速生成代码供我们复制,既不会出错,同时在UI量多了之后可以大大减少我们书写代码的工作量。

首先要会一点关于Unity3D编辑器扩展的知识,如果不是很了解,可以看我相关的文章,相信你看一遍就恍然大悟,自己也可以根据自己的需求完成相关小工具开发了。


开发思路

UGUI UI工作流:我们使用UGUI做UI,往往是将UI拼接好,然后保存成Prefab,再通过代码加载Prefab,并通过获取Prefab实例上需要动态修改的UI节点引用,进行动态操作。

  1. 标记需要保存引用的UI节点。 我们这里采用将选中的UI节点的Name前后分别加上"["与"]"符号。例如:CommitBtn标记后为:[CommitBtn]
  2. 标记UI节点后,保存修改到Prefab,选中相应Prefab,右键GenCode选项,弹出窗口根据我们代码模块生成代码。
  3. 分析我们所需的代码模块:例如我这里是在Lua中使用,形如:self.commitBtn=self:FindChild("...");

功能实现

  1. 在Hierarchy面板选中物件,右键Mark选项,标记物件。或者UnMark选项,取消标记。
    [MenuItem("GameObject/Mark",false,11)]
    static void AddTag()
    {
        GameObject[] curArr = Selection.gameObjects;
        if(curArr.Length!=0)
        {
            for(int i=0;i<curArr.Length;i++)
            {
                if(!curArr[i].name.StartsWith("["))
                {
                    Undo.RecordObject(curArr[i],"AddTag");
                    curArr[i].name="["+curArr[i].name+"]";
                }
            }
        }
    }

    [MenuItem("GameObject/UnMark",false,11)]
    static void RemoveTag()
    {
        GameObject[] curArr=Selection.gameObjects;
        if(curArr.Length!=0)
        {
            for (int i=0;i<curArr.Length;i++)
            {
                Undo.RecordObject(curArr[i],"RemoveTag");
                curArr[i].name=curArr[i].name.Replace("[","");
                curArr[i].name=curArr[i].name.Replace("]","");
            }
        }
    }
  1. 根据所需代码模块,右键Prefab,GenCode选项,弹窗,批量生成标记物件的相关操作代码
    [MenuItem("Assets/GenCode",true)]
    static bool IsCanDo()
    {
        if(PrefabUtility.GetPrefabAssetType(Selection.activeObject)==PrefabAssetType.Regular)
        {
            return true;
        }
        return false;
    }
    
    //此处使用str拼接,可以通过文件操作读取代码模版,进行输出
    static string str="";

    [MenuItem("Assets/GenCode",false)]
    static void GenCode()
    {
        GameObject curGO = Selection.activeObject as GameObject;
        str="";
        GenerateCode(curGO.transform,"");
        MarkTools codeWindow = EditorWindow.GetWindow<MarkTools>("Generate Code");
        codeWindow.Show();
    }

    static void GenerateCode(Transform tf,string path)
    {
        if(tf==null)
            return;
        for(int i=0;i<tf.childCount;i++)
        {
            string curName = tf.GetChild(i).name;
            string curPath = path + curName;
            if(curName.StartsWith("[") && curName.EndsWith("]"))
            {
                str+="self.";
                string varName= GetStanardVarName(curName);
                str += varName + "= self:FindChild(\"" + curPath + "\"";
                str += "\n";
            }

            GenerateCode(tf.GetChild(i),curPath + "/");
        }
    }

    static string GetStanardVarName(string name)
    {
        //去掉"["和"]"
        name = name.Substring(1, name.Length - 2);
        string firstAlpha = name[0].ToString().ToLower();
        name = firstAlpha + name.Substring(1);
        return name;
    }

    void OnGUI()
    {
        EditorGUILayout.TextArea(str);
    }

扩展:以上都是使用最简陋的方法实现批量生成标记物件代码,可以通过文件操作读取你自己的代码模板,生成更加标准的代码。甚至还可以添加增量生成等更进一步的优化。


完整代码

using UnityEngine;
using UnityEditor;

public class MarkTools:EditorWindow
{
    [MenuItem("GameObject/Mark",false,11)]
    static void AddTag()
    {
        GameObject[] curArr = Selection.gameObjects;
        if(curArr.Length!=0)
        {
            for(int i=0;i<curArr.Length;i++)
            {
                if(!curArr[i].name.StartsWith("["))
                {
                    Undo.RecordObject(curArr[i],"AddTag");
                    curArr[i].name="["+curArr[i].name+"]";
                }
            }
        }
    }

    [MenuItem("GameObject/UnMark",false,11)]
    static void RemoveTag()
    {
        GameObject[] curArr=Selection.gameObjects;
        if(curArr.Length!=0)
        {
            for (int i=0;i<curArr.Length;i++)
            {
                Undo.RecordObject(curArr[i],"RemoveTag");
                curArr[i].name=curArr[i].name.Replace("[","");
                curArr[i].name=curArr[i].name.Replace("]","");
            }
        }
    }

    [MenuItem("Assets/GenCode",true)]
    static bool IsCanDo()
    {
        if(PrefabUtility.GetPrefabAssetType(Selection.activeObject)==PrefabAssetType.Regular)
        {
            return true;
        }
        return false;
    }

    static string str="";

    [MenuItem("Assets/GenCode",false)]
    static void GenCode()
    {
        GameObject curGO = Selection.activeObject as GameObject;
        str="";
        GenerateCode(curGO.transform,"");
        MarkTools codeWindow = EditorWindow.GetWindow<MarkTools>("Generate Code");
        codeWindow.Show();
    }

    static void GenerateCode(Transform tf,string path)
    {
        if(tf==null)
            return;
        for(int i=0;i<tf.childCount;i++)
        {
            string curName = tf.GetChild(i).name;
            string curPath = path + curName;
            if(curName.StartsWith("[") && curName.EndsWith("]"))
            {
                str+="self.";
                string varName= GetStanardVarName(curName);
                str += varName + "= self:FindChild(\"" + curPath + "\"";
                str += "\n";
            }

            GenerateCode(tf.GetChild(i),curPath + "/");
        }
    }

    static string GetStanardVarName(string name)
    {
        //去掉"["和"]"
        name = name.Substring(1, name.Length - 2);
        string firstAlpha = name[0].ToString().ToLower();
        name = firstAlpha + name.Substring(1);
        return name;
    }

    void OnGUI()
    {
        EditorGUILayout.TextArea(str);
    }
}

总结

通过以上的扩展工具,我们在使用UGUI的时候能够节省不少的代码工作量,并且不会再出现输入的误差。
但是他只是一个非常粗糙的工具,还需要更进一步优化和修改成你自己所需的工具,这里只是做一个抛砖引用。

优化路线:1.需要支持代码模版,2.需要添加增量优化(生成你以前没有生成过的代码,而不是所有的都生成),3.可否直接生成完整代码,而不是代码片段。

  • 本文作者: Calmer
  • 本文链接: https://mytechplayer.com/archives/unity3deditor扩展快速生成自己的ui代码
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
# 工具链
SVN的使用与搭建(含Unity3D扩展SVNTools)
游戏开发入门概述
  • 文章目录
  • 站点概览
Calmer

Calmer

88 日志
7 分类
10 标签
RSS
Creative Commons
0%
© 2020 — 2025 Calmer
由 Halo 强力驱动
蜀ICP备20010026号-1川公网安备51019002006543
Copyright © 2020-2025 Calmer的文章