Loop List
Introduction
Description
In game development, we often need to display large amounts of list data, such as:
- Hundreds or thousands of items in inventory systems
- Large amounts of player data in leaderboards
- Message history in chat systems
- Product lists in shops
If we create a UI object for each data item, it would not only consume a lot of memory but also cause serious performance issues. The loop list reuses a small number of UI objects to display large amounts of data, only creating objects within the visible area and dynamically updating content when scrolling. This mechanism greatly reduces memory usage and improves performance, making it a best practice for handling large amounts of list data in game development.
Core Features
- Object Reuse: Only creates items needed in the visible area
- Automatic Recycling: Items outside the visible area are automatically recycled
- Performance Optimization: Minimizes memory usage and rendering overhead
- Flexible Configuration: Supports vertical and horizontal scrolling, grid layouts
UI Interface Code Usage Demonstration
Video Tutorial
The following video demonstrates the process of generating common UI component code using the UI framework
Video Operation Introduction
- Creating Loop List: As seen in the video, a
Horizontal
type loop list was created, named:ELoopScrollList_Test
- Creating Loop List Item: Also created an object named:
Item_Test
, placed in theAssets/Bundles/UI/Item
folder, and generated corresponding code files like withCommon
- Specifying Item for Loop List: Also specified the name of the
Item
prefab to be used on theLoop Horizontal Scroll Rect
component on the loop listELoopScrollList_Test
, which will later be loaded throughYooAsset
resource management
Note
Item
must have the Layout Element
component attached to successfully generate code
UI File Structure
Generated script files will be in the following directories:
Scripts
├── UI
│ ├── HotfixView
│ │ └── UIItemBehaviour
│ │ └── Item_TestViewSystem.cs //Logic script
│ │
│ └── ModelView
│ └── UIItemBehaviour
│ └── Item_Test.cs //Data binding script
└── ...
Item_TestViewSystem.cs
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
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;
}
}
Basic Usage
Creating Loop List
Back to the previously mentioned DlgLoginSystem.cs
using the loop list we just added.
DlgLoginSystem.cs
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
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
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();
}
}
}
Effect Demonstration
Effect Video
The following video demonstrates the operation effect of the loop list in the UI framework
This completes the operation of the loop list, initializing and displaying 100 data items.
List Item Optimization Considerations
- Use object pooling
- ...
Technical Support
Get Help
- 💬 Join QQ group for discussion
(ET Framework Group)
: 474643097 - ⭐ Follow the project on GitHub for the latest updates