- 你还在为 UI代入时要写大量的Find代码 而头疼吗?
- 你还在为 UI代入时Find代码中经常眼睛一花写错路径 而恼火吗?
- 你还在为 UI迭代时频繁的变跟子物体名字与结构而需要不断修改代码 而烦恼吗?
- 有了它,你就不再需要这些烦恼了!
前言
在开始工作之后,日常工作中经常会出现这样的情况:
- UI资源有了更新,UI的预制体或是名字发生改变、或是结构发生改变,这时程序就必须得对代码进行修改,来适应新的结构与名字
- 其次,经常需要写重复的代码Find一个子物体,而Find子物体的路径的容错率为0,影响了开发效率
- 最后,第一次Find物体的时候都是在运行时执行的,那么这难免需要一定的损耗,特别是当需要Find的内容较多的时候。
于是,就有了这个UI工具的出现,这个UI工具就是为了解决以上几个问题
成品截图
代码在最后~
如何使用
- 对应功能的子物体在制作时需要自行制定一定的命名规范,如:
- 按钮功能一律命名为btn_xxx
- 图片功能命名为image_xxx
- 滚动条功能一律命名为sli_xxx
- 每次修改预制体后,提交者需要点击图中“点击自动获取所有子物体”(俗称刷一下)就完成了。这样即使结构发生了改变,只要这个改变不是功能性的,那么程序就完全不需要去修改自己的代码。
需要做什么
- 定制一个命名规范
- 定制每个命名对应的组件名(“这个是为了用来自动生成得到子物体的初始化代码,省去了重复写各种Find代码的无意义工作”)
- “刷一下”功能
- 得到所有符合命名规范的子物体并存放他们的相关信息(编辑模式与运行模式都可以使用:一般只在编辑模式使用这个功能)
- 重写这个工具的面板内容来增删改查这些内容
整体思路
- 定制命名规范,以及每个命名对应的组件名
- 创建存放数据的字典:key为子物体名,value为子物体引用
- 创建“刷一下”功能,将所有符合命名规范的子物体信息存入这个数据字典中
- 创建泛型方法,传入关键词key,根据泛型的类型来返回key对应子物体身上的组件
- 创建方法,用于 一键拷贝 所有子物体前缀对应组件的变量的声明、调用泛型方法为这个变量赋值。如下代码(以下代码只是简化版本),下面的代码将全部由面板上的拷贝按钮生成,不需要自己手动写任何代码
private Button btn_OK;
private GameObject go_effect ;
private void Awake()
{
UIViewTools tool = transform.GetComponent<UIViewTools>();
btn_OK = tool.GetComponentByObjectName<Button>("btn_OK");
go_effect = t.GetComponentByObjectName<GameObject>("go_effect ");
}
正题内容
- 第一步:定制规范,首先创建一个UIViewToolEnv类存放各种定制的规范对应的数据
//所有的指定的规范 前缀名的集合
public static readonly List<string> headKeyLists = new List<string>
{
//......具体内容
};
//每个前缀对应的 组件名 集合
public static readonly Dictionary<string,string> varMessage = new Dictionary<string, string>
{
//......具体内容
};
- 第二步:创建类UIViewTool(这个就是主要使用的挂载在预制上的脚本),创建存放子物体信息的字典与增减方法(这里为了区分手动增加与自动增加,所以创建两套方便管理)
PS: 这里额外创建了几个List用来存放编辑模式下的数据,这是因为为了省时间我没有定义一个自己的结构来存放key与GameObject,而字典类型在编辑面板上不易于增删改查,并且字典不能被序列化保存(使用插件除外),所以先用List来存放(这其实是不对的,你们自己做的时候可以自己去建一个类型来存放这些数据,以及增删改查方法等)
public Dictionary<string,GameObject> autoObjDic = new Dictionary<string, GameObject>();
public Dictionary<string,GameObject> handAutoObjDic = new Dictionary<string, GameObject>();
private void AddAutoObjItem(string key,GameObject go)
{
//......
}
public void AddHandObjItem(string key,GameObject go)
{
//......
}
/// <summary>
/// 这里额外用List是为了在面板上更好操作数据,其实最好的办法是自己实现一个结构
/// 而不使用字典和list,但目前为了更快的实现功能所以先这样凑合啦。
/// </summary>
private bool isInit=false;
public List<string> objAutoKeyLists=new List<string>();
public List<GameObject> objAutoLists=new List<GameObject>();
public List<string> objHandKeyLists=new List<string>();
public List<GameObject> objHandLists=new List<GameObject>();
private void Awake()
{
InitData();
}
/// <summary>
/// 运行时Awake以及第一次使用时判断是否初始化,
/// 为初始化则调用这个方法将List数据转为字典
/// 这是为了在使用时更方便
/// </summary>
public void InitData()
{
///......
}
- 第三步:创建“刷一下”方法,刷新所有子物体信息,存放符合规范的子物体的信息
public void FindAllChild_With