文档章节

Unity 获取UI界面结构的工具

o
 osc_z1hvg4cu
发布于 2018/04/24 22:04
字数 875
阅读 10
收藏 0

精选30+云产品,助力企业轻松上云!>>>

  开发的时候必不可少的需要要获取一个界面的子对象组件,虽然很简单但是如果每次获取都敲一次代码,也是一键很恐怖的事情。

  现在项目用了一个工具,对着界面点一下,就会导出匹配这个界面结构的类。只要初始化这个类,就可以很方便的获取这个界面子对象的组件。

  工具思路是这样的:

  1、根据子对象的命名来确定需要获取的组件。比如后缀_txt表示UILabel,_go表示GameObject。

  2、遍历所有子对象,将带后缀的子对象缓存起来。

  3、根据缓存的子对象,按照一定字符串拼接规则,写到本地脚本。

  一个界面结构和导出的界面脚本结果如下

  

  只要把界面的资源(Gameobject)传进去,就可以直接获取子对象的组件,大大提高了开发效率。当然了,工程里对这个脚本进行了一系列封装和抽象,这里是单独摘出来演示的。

  (ps:这是我第一个项目,所以不清楚其他项目怎么处理这个问题的,如果有更好的思路务必告诉我)

  闲话少说,直接上干货。(注释写的比较全,就不秀我那渣渣的表达能力了)

  工具脚本:

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

public class CreateSprite {
    //当前操作的对象
    private static GameObject CurGo;
    //后缀对应的组件类型
    public static Dictionary<string, string> typeMap = new Dictionary<string, string>()
    {   
        { "sp", typeof(UISprite).Name },
        { "txt", typeof(UILabel).Name },
        { "btn", typeof(UIButton).Name },
        { "go", typeof(GameObject).Name},
    };
    //脚本模版
    private static CreateSpriteUnit info;

    //在Project窗口下,选中要导出的界面,然后点击GameObject/导出脚本
    [MenuItem("GameObject/导出脚本")]
    public static void CreateSpriteAction()
    {
        GameObject[] gameObjects = Selection.gameObjects;
        //保证只有一个对象
        if (gameObjects.Length==1)
        {
            info = new CreateSpriteUnit();
            CurGo = gameObjects[0];
            ReadChild(CurGo.transform);
            info.classname = CurGo.name + "UIPanel";
            info.WtiteClass();
            info = null;
            CurGo = null;
        }
        else
        {
            EditorUtility.DisplayDialog("警告", "你只能选择一个GameObject", "确定");
        }
    }
    //遍历所有子对象,GetChild方法只能获取第一层子对象。
    public static void ReadChild(Transform tf)
    {
        foreach (Transform child in tf)
        {
            string[] typeArr = child.name.Split('_');
            if (typeArr.Length > 1)
            {
                string typeKey = typeArr[typeArr.Length - 1];
                if (typeMap.ContainsKey(typeKey))
                {
                    info.evenlist.Add(new UIInfo(child.name, typeKey, buildGameObjectPath(child).Replace(CurGo.name + "/","")));
                }

            }
            if (child.childCount > 0)
            {
                ReadChild(child);
            }
        }
    }
    //获取路径,这个路径是带当前对象名的,需要用Replace替换掉头部
    private static string buildGameObjectPath(Transform obj)
    {
        var buffer = new StringBuilder();

        while (obj != null)
        {
            if (buffer.Length > 0)
                buffer.Insert(0, "/");
            buffer.Insert(0, obj.name);
            obj = obj.parent;
        }
        return buffer.ToString();
    }
}
//导出脚本的模版
public class CreateSpriteUnit
{
    public string classname;
    public string template = @"
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class @ClassName 
{   
@fields

    public void OnAwake(GameObject viewGO)
    {
@body1
    }

    public void OnDestroy()
    {
@body2
    }
}
";
    //缓存的所有子对象信息
    public List<UIInfo> evenlist = new List<UIInfo>();
    /// <summary>
    /// 把拼接好的脚本写到本地。
    /// (自己可以个窗口支持改名和选择路径,真实工程里是带这些功能的)
    /// </summary>
    public void WtiteClass()
    {
        bool flag = true;
        bool throwOnInvalidBytes = false;
        UTF8Encoding encoding = new UTF8Encoding(flag, throwOnInvalidBytes);
        bool append = false;
        StreamWriter writer = new StreamWriter(Application.dataPath + "/" + classname + ".cs", append, encoding);
        writer.Write(GetClasss());
        writer.Close();
        AssetDatabase.Refresh();
    }
    //脚本拼接
    public string GetClasss()
    {
        var fields = new StringBuilder();
        var body1 = new StringBuilder();
        var body2 = new StringBuilder();
        for (int i = 0; i < evenlist.Count; i++)
        {
            fields.AppendLine("\t" + evenlist[i].field);
            body1.AppendLine("\t\t" + evenlist[i].body1);
            body2.AppendLine("\t\t" + evenlist[i].body2);
        }
        template = template.Replace("@ClassName", classname).Trim();
        template = template.Replace("@body1", body1.ToString()).Trim();
        template = template.Replace("@body2", body2.ToString()).Trim();
        template = template.Replace("@fields", fields.ToString()).Trim();
        return template;
    }
}
//子对象信息
public class UIInfo{
    public string field;
    public string body1;
    public string body2;
    public UIInfo(string name, string typeKey, string path)
    {
        field = string.Format("public {0} {1};", CreateSprite.typeMap[typeKey], name);
        if (typeKey == "go")
        {
            body1 = string.Format("{0} = viewGO.transform.Find(\"{1}\").gameObject;", name, path, CreateSprite.typeMap[typeKey]);
        }
        else
        {
            body1 = string.Format("{0} = viewGO.transform.Find(\"{1}\").GetComponent<{2}>();", name, path, CreateSprite.typeMap[typeKey]);
        }
        body2 = string.Format("{0} = null;", name);
    }
}

 

 

  

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

Linux安装redis服务器和部署

Linux安装redis和部署 第一步:下载安装包 wget http://download.redis.io/releases/redis-5.0.5.tar.gz 访问https://redis.io/download 到官网进行下载。这里下载最新的5.0.5版本. 第二步:...

osc_3ytpwpyb
14分钟前
11
0
IF函数,根据条件设定输入内容

if函数通常用于条件判断,根据判断结果执行相应命令。 1.函数解释: IF(logical_test, [value_if_true], [value_if_false]) logical_test 必需。 计算结果为 TRUE 或 FALSE 的任何值或表达式...

osc_sumf8h95
16分钟前
5
0
Pytorch自定义dataloader以及在迭代过程中返回image的name

pytorch官方给的加载数据的方式是已经定义好的dataset以及loader,如何加载自己本地的图片以及label? 形如数据格式为 image1 label1 image2 label2 ... imagen labeln 实验中我采用的数据的...

osc_l8u38961
17分钟前
0
0
灯塔

\[love\ and \ share \] 我怎么感觉变成了好东西推荐呢?算了,本来也差不多 还没写完,想到再更 有好看玩的能不能评论一下,qwq 动漫 大多是些国漫,多在\(b\)站、腾讯视频、盗版小网站能够...

osc_dc6pbw3x
18分钟前
0
0
网易首页 」 网易手机 」 正文 苹果超薄触摸显示技术专利曝光:重新定义轻薄

最近,苹果公司的新屏幕专利技术已经曝光。特别是苹果公司的新型超薄触摸技术,它可以降低显示器的结构水平,消除多余的电路,并使屏幕更薄。该专利表明,这项新技术适用于iPhone,iPad,App...

osc_opzpp18v
20分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部