1.介绍
在做一次性加载同一种预制体多个时(如排行榜,背包等),循环列表必不可少,它能帮你大大降低卡顿和提高性能。以下是我封装的基于EUI的循环列表,个人觉得封装的还不错。如果使用有遇到bug或者还有什么新需求可以留言或者提交pr。
陈芬辉/ET - Gitee.comhttps://gitee.com/chen_fen_hui/ET/tree/ETPro
2.核心代码解析(DynamicInfinityList.cs)
protected void UpdateRender()
{
//更新检测框区域
if(MotionType == MotionEnum.Vertical)
mRectMask.y = -mMaskSize.y - mRectTransformContainer.anchoredPosition.y + Margin.top;
else
mRectMask.x = -mRectTransformContainer.anchoredPosition.x + Margin.left;
//记录与检测框相交的item
Dictionary<int, DynamicRect> inOverlaps = new Dictionary<int, DynamicRect>();
foreach (DynamicRect dR in mDict_dRect.Values)
{
if (dR.Overlaps(mRectMask))
{
inOverlaps.Add(dR.Index, dR);
}
}
//如果上一帧有,这一帧没有就隐藏并调用销毁事件
for (int i = 0; i < lastRenderList.Count; i++)
{
if (!inOverlaps.ContainsKey(lastRenderList[i]))
{
if (!itemsDic.TryGetValue(lastRenderList[i], out Transform tr))
{
Debug.LogError("itemsDic has not found render!");
return;
}
OnHideItem?.Invoke(lastRenderList[i]);
tr.gameObject.SetActive(false);
}
}
//如果这一帧有,上一帧没有就显示并调用刷新事件
foreach (int key in inOverlaps.Keys)
{
if (!lastRenderList.Contains(key))
{
Transform item = GetNullDynmicItem(key);
UpdateChildTransformPos(item, key);
item.gameObject.SetActive(true);
itemsDic.Add(key, item);
if (key < numItems)
{
OnShowItem?.Invoke(item, key);
}
}
}
//记录这一帧的渲染格子
lastRenderList.Clear();
lastRenderList = inOverlaps.Keys.ToList();
}
3.使用
1.右键LoopHorizontalList/LoopVerticalList创建横向/竖向循环列表
2.设置DynamicInfinityList的参数
3.选中Dlg和ESItem预制体分别右键SpawnEUICode自动生成代码
4.在Dlg+system逻辑层调用
public static class DlgLoginSystem
{
public static void RegisterUIEvent(this DlgLogin self)
{
//注册显示和销毁事件
self.View.EList_test.InitRendererList(self.OnShowItem, self.OnHideItem);
}
private static void OnShowItem(this DlgLogin self, Transform tr, int index)
{
//从对象池添加ESItemTest实体并绑定Transform
ESItemTest item = self.AddChildWithId<ESItemTest, Transform>(index, tr, true);
item.EText_count.text = index.ToString();
item.EButton_add.AddListener(() =>
{
//移动到指定的格子位置
self.View.EList_test.ScrollToIndex(index, 0.1f);
});
}
private static void OnHideItem(this DlgLogin self, int index)
{
//将隐藏的格子实体扔进对象池
ESItemTest item = self.GetChild<ESItemTest>(index);
item.Dispose();
}
//显示界面触发函数
public static void ShowWindow(this DlgLogin self, Entity contextData = null)
{
//循环列表的总个数
self.View.EList_test.NumItems = 100;
}
//隐藏界面触发函数
public static void HideWindow(this DlgLogin self)
{
//回收所有格子
self.View.EList_test.HideAllRender();
}
}