游戏开发实战Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)
Posted 林新发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏开发实战Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)相关的知识,希望对你有一定的参考价值。
文章目录
一、前言
嗨,大家好,我是新发。
有小伙伴在提问区问Unity
如何实现不规则循环复用列表,
我今天发现GitHub
上已经有人实现了一个版本,效果可以,
GitHub
地址:https://github.com/aillieo/UnityDynamicScrollView
不过这个版本有个BUG
,我做了修复,本文第三部分有说明。
好轮子大家用,今天我就介绍一下这个版本的使用方法吧~
本文最终效果如下
二、使用方法
1、创建Scroll View
在UI
节点上创建一个Scroll View
,
如下
将Scroll View
节点的Scroll Rect
组件移除,如下
挂上代码中的ScrollView
组件或ScrollViewEx
组件,我这里以ScrollViewEx
组件为例,
注:
ScrollViewEx
继承了ScrollView
的所有功能,并进行了针对性的优化,它会对item
进行分页,设置适当的页面尺寸可以得到更好的性能表现
挂上组件后效果如下,
2、设置Scroll View参数
2.1、调整宽高
我们先调整一下Scroll View
的宽高,
2.2、删除Scrollbar滑块
我们看到Scroll View
带了两个Scrollbar
滑块,我们不想要它,
可以直接把子节点下的Scrollbar Horizontal
和Scrollbar Vertical
删除,
删除后可以看到Viewport
之前给Scrollbar
留了空间,现在没有Scrollbar
了,我们要调节一下Viewport
使其填充整个Scroll View
,
我们选中Viewport
,把Right
和Bottom
都改为0
,
如下
2.3、设置item模板: Item Template
列表中要显示一个一个的item
,得先做item
模板,我们在Scroll View
子节点下创建一个Image
,重命名为item
,如下,
调整一下item
的宽高,
如下,
接着选中Scroll View
节点,设置Item Template
为刚刚的item
,并填写Default Item Size
为item
的宽高,如下
2.4、设置对象池大小:Pool Size
为了防止列表item
的重复创建销毁,这里用到了对象池,我们需要设置一下对象池大小Pool Size
。如果一直往对象池塞对象(只塞不取),对象池满了之后,就不再继续塞对象到对象池中,我们需要设置合理的对象池大小,建议是列表可见区域能够显示的item
的最大数量的2倍
,这里我预估列表可见区域最多显示10
个item
,那么我对象池大小设置为20
,
2.5、设置列表排列方向
列表提供了4
种排列方向,大家一看选项就知道是什么意思了,这里我以Vertical
为例,
2.6、设置分页大小: Page Size
如果你用的是ScrollView
组件就没有Page Size
这个设置了,只有ScrollViewEx
组件有这个设置。
为什么要设置分页呢?ScrollView
中维护了一份List<ScrollItemWithRect>
,用于存储item
的坐标和尺寸,
假设你的列表有巨量的item
数据,你现在要往中间插入一个新的item
,这个时候要重新计算巨量的item
的坐标和尺寸,非常的耗性能,解决办法就是设置分页,每次只维护一个分页的item
,大大提升性能。
建议设置为列表可见区域能够显示的item
的最大数量的2倍
以上,这里设置为30
,
2.7、其他常规设置
设置一下Content
和Viewport
,如下
根据滑动方向勾选Horizontal
或Vertical
,这里我只需竖直方向滑动,所以只勾选Vertical
,
3、给item加点元素
上面我们的item
光溜溜的,给它加点元素,再微调一下整体界面,如下
节点结构如下
4、写测试代码
创建一个MyTest.cs
脚本,如下,
注:
TestScript.cs
和TestLargeAmount.cs
是原作者提供的测试脚本。
先定义一个数据结构体
// MyTest.cs
public struct RankItemData
// 名次
public int rank;
// 名字
public string name;
声明一个List
对象,用于存储列表数据,
// MyTest.cs
List<RankItemData> testData = new List<RankItemData>();
现在我们写个方法来构造一些测试数据,
// MyTest.cs
private void Start()
// 构造测试数据
InitData();
private void InitData()
// 构建50000个排名数据
for (int i = 1; i <= 50000; ++i)
RankItemData data = new RankItemData();
data.rank = i;
data.name = "Name_" + i;
testData.Add(data);
声明ScrollView
成员对象,并给ScrollView
设置回调函数,如下
// MyTest.cs
using System.Collections.Generic;
using UnityEngine;
using AillieoUtils;
public class MyTest : MonoBehaviour
...
public ScrollView scrollView;
private void Start()
...
scrollView.SetUpdateFunc((index, rect) =>
// TODO 更新item的UI元素
);
scrollView.SetItemSizeFunc((index) =>
// TODO 返回item的尺寸
return Vector2.one;
);
scrollView.SetItemCountFunc(() =>
// TODO 返回数据列表item的总数
return 0;
);
接下来我们挨个实现回调的具体内容。
更新item
的UI
元素,
// MyTest.cs
scrollView.SetUpdateFunc((index, rectTransform) =>
// 更新item的UI元素
RankItemData data = testData[index];
rectTransform.gameObject.SetActive(true);
rectTransform.Find("rankText").GetComponent<Text>().text = data.rank.ToString();
rectTransform.Find("nameText").GetComponent<Text>().text = data.name;
Button btn = rectTransform.Find("Button").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(()=>
Debug.Log(data.name);
);
);
返回item
的尺寸,我希望前三名的item
高度高一些,返回Vector2(812, 180)
,其他的返回Vector2(812, 100)
,
// MyTest.cs
scrollView.SetItemSizeFunc((index) =>
// 返回item的尺寸
RankItemData data = testData[index];
if(data.rank <= 3)
return new Vector2(812, 180);
else
return new Vector2(812, 100);
);
返回数据列表item
的总数,
// MyTest.cs
scrollView.SetItemCountFunc(() =>
// 返回数据列表item的总数
return testData.Count;
);
5、运行测试
我们将MyTest.cs
脚本挂到Canvas
上,并赋值Scroll View
成员,如下,
接着,我们把item
隐藏掉,
运行,效果如下,
嗯,item
与item
之间少了间隔,我们改造一下。
6、item直接增加间隔
在item
下创建一个Image
并重命名为bg
,设置Anchors
为stretch-strech
,设置Top
和Bottom
位2
,这样就会上下留2
个单位的缝隙了,
我们把item
自身的Image
组件删掉,重新运行,效果如下,达到我们的效果了
我们可以看到,虽然我们的列表数据有50000
个,但UI
只有几个item
在循环复用着,特别适合用于数据项很多的列表的显示,
三、BUG修复
测试的时候发现一个BUG
,使用ScrollViewEx.cs
时,翻页的时候,在边界时会疯狂触发OnValueChanged
导致快速翻页,
我在Demo
做了修复,增加了一个阻尼,避免疯狂翻页。
四、Demo源码
本文Demo
源码我已上传到GitCode
,感兴趣的同学可自行下载学习。
地址:https://codechina.csdn.net/linxinfa/UnityDynamicScrollView
五、完毕
好了,就写到这里吧。
我是新发,https://blog.csdn.net/linxinfa
一个在小公司默默奋斗的Unity
开发者,希望可以帮助更多想学Unity
的人,共勉~
以上是关于游戏开发实战Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)的主要内容,如果未能解决你的问题,请参考以下文章
游戏开发实战Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)
游戏开发实战Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)