循环列表
简介
说明
在游戏开发中,我们经常需要展示大量的列表数据,比如:
- 背包系统中成百上千的道具
- 排行榜中大量的玩家数据
- 聊天系统中的消息记录
- 商城中的商品列表
如果为每一条数据都创建一个UI对象,不仅会占用大量内存,还会导致严重的性能问题。循环列表通过复用少量UI对象来展示大量数据,只创建可视区域内的对象,并在滚动时动态更新内容。这种机制可以大大降低内存占用和提升性能,是游戏开发中处理大量列表数据的最佳实践。
核心特性
- 对象重用: 只创建可视区域所需的项目
- 自动回收: 超出可视区域的项目自动回收
- 性能优化: 最小化内存占用和渲染开销
- 灵活配置: 支持垂直和水平方向的滚动、网格布局
构建UI界面代码使用演示
视频教程
以下视频展示了UI框架生成通用UI组件代码的使用流程
视频内操作介绍
- 循环列表的创建:可以看到视频内创建了一个
Horizontal
类型的循环列表,命名为:ELoopScrollList_Test
- 循环列表的Item创建:同时也创建了一个名为:
Item_Test
的物体,放在了Assets/Bundles/UI/Item
文件夹下,同时跟Common
一样为生成其对应的代码文件 - 循环列表指定Item:同时在循环列表
ELoopScrollList_Test
身上的Loop Horizontal Scroll Rect
组件指定了一下当前循环列表要用的Item
预制体名称,后续会通过YooAsset
资源管理去加载对应的Item
注意
Item
必须要挂载组件Layout Element
才能成功生成代码
UI文件结构
生成的脚本文件会对应在如下目录:
Scripts
├── UI
│ ├── HotfixView
│ │ └── UIItemBehaviour
│ │ └── Item_TestViewSystem.cs //编写逻辑的脚本
│ │
│ └── ModelView
│ └── UIItemBehaviour
│ └── Item_Test.cs //数据绑定的脚本
└── ...
Item_TestViewSystem.cs
csharp
using UnityEngine;
using UnityEngine.UI;
namespace MH
{
[EntitySystem]
public class Scroll_Item_TestAwakeSystem : AwakeSystem<Scroll_Item_Test>
{
protected override void Awake(Scroll_Item_Test self)
{
}
}
[EntitySystem]
public class Scroll_Item_TestDestroySystem : DestroySystem<Scroll_Item_Test>
{
protected override void Destroy(Scroll_Item_Test self)
{
self.DestroyWidget();
}
}
public static partial class Scroll_Item_TestViewSystem
{
}
}
Item_Test.cs
csharp
using UnityEngine;
using UnityEngine.UI;
namespace MH
{
public partial class Scroll_Item_Test : Entity,IAwake,IDestroy,IUIScrollItem<Scroll_Item_Test>,IUILogic
{
public long DataId {get;set;}
private bool isCacheNode = false;
public void SetCacheMode(bool isCache)
{
this.isCacheNode = isCache;
}
public Scroll_Item_Test BindTrans(Transform trans)
{
this.uiTransform = trans;
return this;
}
public UnityEngine.UI.Image E_IconImage
{
get
{
if (this.uiTransform == null)
{
Debug.LogError("uiTransform is null.");
return null;
}
if (this.isCacheNode)
{
if( this.m_E_IconImage == null )
{
this.m_E_IconImage = UIFindHelper.FindDeepChild<UnityEngine.UI.Image>(this.uiTransform.gameObject,"E_Icon");
}
return this.m_E_IconImage;
}
else
{
return UIFindHelper.FindDeepChild<UnityEngine.UI.Image>(this.uiTransform.gameObject,"E_Icon");
}
}
}
public UnityEngine.UI.Text E_NumText
{
get
{
if (this.uiTransform == null)
{
Debug.LogError("uiTransform is null.");
return null;
}
if (this.isCacheNode)
{
if( this.m_E_NumText == null )
{
this.m_E_NumText = UIFindHelper.FindDeepChild<UnityEngine.UI.Text>(this.uiTransform.gameObject,"E_Icon/E_Num");
}
return this.m_E_NumText;
}
else
{
return UIFindHelper.FindDeepChild<UnityEngine.UI.Text>(this.uiTransform.gameObject,"E_Icon/E_Num");
}
}
}
public void DestroyWidget()
{
this.m_E_IconImage = null;
this.m_E_NumText = null;
this.uiTransform = null;
this.DataId = 0;
}
private UnityEngine.UI.Image m_E_IconImage = null;
private UnityEngine.UI.Text m_E_NumText = null;
public Transform uiTransform = null;
}
}
基础用法
创建循环列表
回到之前的DlgLoginSystem.cs
使用刚刚添加的循环列表。
DlgLoginSystem.cs
csharp
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace MH
{
public static class DlgLoginSystem
{
public static void RegisterUIEvent(this DlgLogin self)
{
self.View.ELoopScrollList_TestLoopHorizontalScrollRect.AddItemRefreshListener(self.OnTestItemLoopRefreshHandler);
}
public static void ShowWindow(this DlgLogin self, Entity contextData = null)
{
self.Refresh();
}
public static void Refresh(this DlgLogin self)
{
self.AddUIScrollItems(ref self.ScrollItemTests, 100);
self.View.ELoopScrollList_TestLoopHorizontalScrollRect.SetVisible(true, 100);
}
public static void OnTestItemLoopRefreshHandler(this DlgLogin self, Transform transform, int index)
{
var scrollItemServer = self.ScrollItemTests[index].BindTrans(transform);
scrollItemServer.Init(index);
}
}
}
DlgLogin.cs
csharp
using System.Collections.Generic;
namespace MH
{
public class DlgLogin :Entity,IAwake,IUILogic
{
public DlgLoginViewComponent View { get => this.GetComponent<DlgLoginViewComponent>();}
public Dictionary<int, Scroll_Item_Test> ScrollItemTests;
}
}
Scroll_Item_TestViewSystem.cs
csharp
using UnityEngine;
using UnityEngine.UI;
namespace MH
{
[EntitySystem]
public class Scroll_Item_TestAwakeSystem : AwakeSystem<Scroll_Item_Test>
{
protected override void Awake(Scroll_Item_Test self)
{
}
}
[EntitySystem]
public class Scroll_Item_TestDestroySystem : DestroySystem<Scroll_Item_Test>
{
protected override void Destroy(Scroll_Item_Test self)
{
self.DestroyWidget();
}
}
public static partial class Scroll_Item_TestViewSystem
{
public static void Init(this Scroll_Item_Test self, int index)
{
self.E_NumText.text = index.ToString();
}
}
}
效果演示
效果视频
以下视频展示了UI框架对循环列表的操作效果演示
这样就完成了对循环列表的操作复制,初始化100
个数据并显示复制。
列表项可优化事项
- 使用对象池
- ...
技术支持
获取帮助
- 💬 加入QQ群讨论交流
(ET框架群)
: 474643097 - ⭐ 在GitHub上关注项目获取最新更新