性能优化

排行榜,邮件,关卡等数据列表项,一般在玩家打开面板时,都会重新刷新一次数据,那是否有必要每次都生成列表项呢?

假如每次列表的内容有变动就Instance 新的Gameobject,这是没有必要的浪费。本文想做的就是避免频繁生成新的Gameobject。

运行效果

UIGrid/UITable 性能优化_NGUI

思路及流程图

循环利用UIGrid下已有child,改变child的数据(不同child渲染不同的数据)。需要生成时就生成,不需要生成则根据情况显示隐藏

流程图如下所示

UIGrid/UITable 性能优化_IT_02

实现方法

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)
    {
        
    }
}