【NGUI】grid下面的item的重复利用

2015年03月19日 14:19 1 点赞 0 评论 更新于 2025-11-21 17:45

问题描述

在使用 Grid 放置 Item 时,每次的数据可能都不同。若每次都删除 Grid 下的节点,再动态创建新的 Item,会造成资源的浪费。

解决方案

我们可以编写一个简单的工具函数来实现 Item 的重复利用,其原理如下:

  1. 首先获取 Grid 下可用的 Item。
  2. 根据数据的数量进行初始化。
  3. 每次从可用的 Item 列表中获取新的 Item,若列表中的 Item 不够用,则创建新的 Item。
  4. 将未使用的 Item 禁用。

注意事项

每个 Grid 下需要预先有一个名字包含 “Template_” 的模板 Item。这个模板不会被使用,因为之前尝试将其作为普通 Item 使用时,部分 NGUI 的 Widget 会出现 BUG。

代码实现

using UnityEngine;
using System.Collections.Generic;

// qq group :333417608
public class UITools
{
/* 使用示例:
List<GameObject> canUseList = UITools.GetCanUseItemList(gridRoot);
for (int i = 0; i < totalData.Length; ++i)
{
GameObject go = UITools.GetNewItemObj(canUseList, gridRoot, prefab);
// 进行初始化操作
}
UITools.UnActiveUnuseItem(canUseList);

// prefab 是模板
*/

/// <summary>
/// 从可用列表中获取新的 Item 对象,若列表为空则创建新的 Item
/// </summary>
/// <param name="canUseList">可用 Item 列表</param>
/// <param name="root">Grid 根对象</param>
/// <param name="prefab">Item 预制体</param>
/// <returns>新的 Item 对象</returns>
static public GameObject GetNewItemObj(List<GameObject> canUseList, GameObject root, GameObject prefab)
{
GameObject go = null;
if (canUseList.Count > 0)
{
go = canUseList[0];
canUseList.RemoveAt(0);
}
else
{
go = NGUITools.AddChild(root, prefab);
}
NGUITools.SetActiveSelf(go, true);
return go;
}

/// <summary>
/// 从可用列表中获取新的 Item 组件,若列表为空则创建新的 Item 并获取其组件
/// </summary>
/// <typeparam name="T">组件类型</typeparam>
/// <param name="canUseList">可用 Item 组件列表</param>
/// <param name="root">Grid 根对象</param>
/// <param name="prefab">Item 预制体</param>
/// <returns>新的 Item 组件</returns>
static public T GetNewItemObj<T>(List<T> canUseList, GameObject root, GameObject prefab) where T : Component
{
T item = null;
if (canUseList.Count > 0)
{
item = canUseList[0];
canUseList.RemoveAt(0);
}
else
{
item = NGUITools.AddChild(root, prefab).GetComponent<T>();
}
item.name = string.Format("{0:D3}", 0);
NGUITools.SetActiveSelf(item.gameObject, true);
return item;
}

/// <summary>
/// 获取 Grid 下可用的 Item 列表
/// </summary>
/// <param name="root">Grid 根对象</param>
/// <returns>可用的 Item 列表</returns>
static public List<GameObject> GetCanUseItemList(GameObject root)
{
List<GameObject> itemList = new List<GameObject>();
Transform rootT = root.transform;
for (int i = 0; i < rootT.childCount; ++i)
{
GameObject go = rootT.GetChild(i).gameObject;
if (IsNotTemplateGameObject(go))
{
itemList.Add(go);
}
}
return itemList;
}

/// <summary>
/// 获取 Grid 下可用的 Item 组件列表
/// </summary>
/// <typeparam name="T">组件类型</typeparam>
/// <param name="root">Grid 根对象</param>
/// <returns>可用的 Item 组件列表</returns>
static public List<T> GetCanUseItemList<T>(GameObject root) where T : Component
{
List<T> childrenList = new List<T>();
Transform rootT = root.transform;
for (int i = 0; i < rootT.childCount; ++i)
{
Transform child = rootT.GetChild(i);
T t = child.GetComponent<T>();
if (t != null && IsNotTemplateGameObject(child.gameObject))
{
childrenList.Add(t);
}
}
return childrenList;
}

/// <summary>
/// 禁用未使用的 Item
/// </summary>
/// <param name="canUseList">可用 Item 列表</param>
static public void UnActiveUnuseItem(List<GameObject> canUseList)
{
foreach (var item in canUseList)
{
NGUITools.SetActiveSelf(item, false);
}
}

/// <summary>
/// 禁用未使用的 Item 组件
/// </summary>
/// <typeparam name="T">组件类型</typeparam>
/// <param name="canUseList">可用 Item 组件列表</param>
static public void UnActiveUnuseItem<T>(List<T> canUseList) where T : Component
{
foreach (var item in canUseList)
{
NGUITools.SetActiveSelf(item.gameObject, false);
}
}

/// <summary>
/// 判断对象是否不是模板对象
/// </summary>
/// <param name="go">要判断的对象</param>
/// <returns>是否不是模板对象</returns>
static private bool IsNotTemplateGameObject(GameObject go)
{
bool result = !go.name.ToLower().Contains("template_");
if (!result && go.activeSelf)
{
NGUITools.SetActiveSelf(go, false);
}
return result;
}
}

通过上述代码,我们实现了 Grid 下 Item 的重复利用,避免了不必要的资源浪费。在实际使用时,可按照代码中的使用示例进行调用。

作者信息

menghao

menghao

共发布了 3994 篇文章