UIGrid/UITable 性能优化
性能优化
排行榜,邮件,关卡等数据列表项,一般在玩家打开面板时,都会重新刷新一次数据,那是否有必要每次都生成列表项呢?
假如每次列表的内容有变动就Instance 新的Gameobject,这是没有必要的浪费。本文想做的就是避免频繁生成新的Gameobject。
运行效果
思路及流程图
循环利用UIGrid下已有child,改变child的数据(不同child渲染不同的数据)。需要生成时就生成,不需要生成则根据情况显示隐藏
流程图如下所示
实现方法
1、创建工具类:动态生成child ,隐藏多余的child
2、工具类使用方法:
传入template obj(prefab)、data ,ResizeGrid
设置每一个Child的内容
XUIHelper
public class XUIHelper { /// <summary> /// 传入指定数量, 对UIGrid里指定数量项SetActive(true)/或创建, 其余的SetActive(false) /// 常用于UIGrid下的对象动态增长 /// </summary> public static void ResizeUIGridGameObjects(UIGrid uiGrid, int resizeCount, GameObject templateForNew = null) { if (templateForNew == null && uiGrid.transform.childCount <= 0) { CDebug.LogError("template为空 && uigrid childCount为0"); return; } if (templateForNew == null) templateForNew = uiGrid.transform.GetChild(0).gameObject; _ResizeUIWidgetContainerGameObjects(uiGrid.transform, resizeCount, templateForNew); uiGrid.Reposition(); } public static void ResizeUITableGameObjects(UITable uiTable, int resizeCount, GameObject templateForNew = null) { if (templateForNew == null && uiTable.transform.childCount <= 0) { CDebug.LogError("template为空 && uigrid childCount为0"); return; } if (templateForNew == null) templateForNew = uiTable.transform.GetChild(0).gameObject; _ResizeUIWidgetContainerGameObjects(uiTable.transform, resizeCount, templateForNew); uiTable.Reposition(); } public static void _ResizeUIWidgetContainerGameObjects(Transform transf, int resizeCount, GameObject templateForNew) { if (templateForNew == null) templateForNew = default(GameObject); for (int i = 0; i < resizeCount; i++) { GameObject newTemplate = null; if (i >= transf.childCount) //child不足 instantiate { newTemplate = Object.Instantiate(templateForNew) as GameObject; newTemplate.transform.parent = transf; ResetLocalTransform(newTemplate.transform); } newTemplate = transf.GetChild(i).gameObject; if (!newTemplate.activeSelf) newTemplate.SetActive(true); } //多余的child setActive(false) for (int i = resizeCount; i < transf.childCount; ++i) { GameObject newTemplate = transf.GetChild(i).gameObject; if (newTemplate.activeSelf) newTemplate.SetActive(false); } } /// <summary> /// 模仿 NGUISelectionTool的同名方法,将位置旋转缩放清零 /// </summary> /// <param name="t"></param> public static void ResetLocalTransform(Transform t) { t.localPosition = Vector3.zero; t.localRotation = Quaternion.identity; t.localScale = Vector3.one; } }
使用方法
public class XUILevel :CUIController { private UIGrid LevelGrid; private List<CLevelInfo> LevelList; private GameObject LevelTemplate; public void RefreshUI() { //刷新Grid XUIHelper.ResizeUIGridGameObjects(LevelGrid, LevelList.Count, LevelTemplate); var idx = 0; foreach (var levelInfo in LevelList) { var child = LevelGrid.transform.GetChild(idx); child.name = "Level-"+levelInfo.Id; GetControl<UILabel>("Label", child).text = levelInfo.Name; child.GetComponent<UIEventListener>().onClick = OnClickLevel; //...... 其它的操作 idx++; } LevelGrid.GetComponent<UIGrid>().enabled = true; LevelGrid.Reposition(); } void OnClickLevel(GameObject obj) { } }