【游戏开发实战】Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码)

2023-05-16

文章目录

      • 一、前言
      • 二、使用方法
        • 1、创建Scroll View
        • 2、设置Scroll View参数
          • 2.1、调整宽高
          • 2.2、删除Scrollbar滑块
          • 2.3、设置item模板: Item Template
          • 2.4、设置对象池大小:Pool Size
          • 2.5、设置列表排列方向
          • 2.6、设置分页大小: Page Size
          • 2.7、其他常规设置
        • 3、给item加点元素
        • 4、写测试代码
        • 5、运行测试
        • 6、item直接增加间隔
      • 三、BUG修复
      • 四、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 HorizontalScrollbar Vertical删除,
在这里插入图片描述
删除后可以看到Viewport之前给Scrollbar留了空间,现在没有Scrollbar了,我们要调节一下Viewport使其填充整个Scroll View
在这里插入图片描述
我们选中Viewport,把RightBottom都改为0
在这里插入图片描述
如下
在这里插入图片描述

2.3、设置item模板: Item Template

列表中要显示一个一个的item,得先做item模板,我们在Scroll View子节点下创建一个Image,重命名为item,如下,
在这里插入图片描述
调整一下item的宽高,
在这里插入图片描述
如下,
在这里插入图片描述
接着选中Scroll View节点,设置Item Template为刚刚的item,并填写Default Item Sizeitem的宽高,如下
在这里插入图片描述

2.4、设置对象池大小:Pool Size

为了防止列表item的重复创建销毁,这里用到了对象池,我们需要设置一下对象池大小Pool Size。如果一直往对象池塞对象(只塞不取),对象池满了之后,就不再继续塞对象到对象池中,我们需要设置合理的对象池大小,建议是列表可见区域能够显示的item的最大数量的2倍,这里我预估列表可见区域最多显示10item,那么我对象池大小设置为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、其他常规设置

设置一下ContentViewport,如下
在这里插入图片描述
根据滑动方向勾选HorizontalVertical,这里我只需竖直方向滑动,所以只勾选Vertical
在这里插入图片描述

3、给item加点元素

上面我们的item光溜溜的,给它加点元素,再微调一下整体界面,如下
在这里插入图片描述
节点结构如下
在这里插入图片描述

4、写测试代码

创建一个MyTest.cs脚本,如下,

注:TestScript.csTestLargeAmount.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;
        });
    }
}

接下来我们挨个实现回调的具体内容。
更新itemUI元素,

// 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隐藏掉,
在这里插入图片描述
运行,效果如下,
请添加图片描述
嗯,itemitem之间少了间隔,我们改造一下。

6、item直接增加间隔

item下创建一个Image并重命名为bg,设置Anchorsstretch-strech,设置TopBottom2,这样就会上下留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的人,共勉~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【游戏开发实战】Unity循环复用列表,支持不规则尺寸(对象池 | UGUI | ScrollRect | Demo源码) 的相关文章

  • [大模拟]Test Week8 二阶魔方

    目录 大模拟 东东玩二阶魔方题意d样例样例输入 xff1a 样例输出 思路总结代码 B 模拟 ST串题意样例样例输入 xff1a 样例输出 xff1a 思路总结代码 大模拟 东东玩二阶魔方 题意d 东东有一个二阶魔方 xff0c 即2 2
  • [大模拟]Test Week14 猫睡觉问题

    目录 大模拟 猫睡觉问题题意样例样例输入 xff1a 样例输出 思路总结代码 大模拟 猫睡觉问题 题意 众所周知 xff0c TT家里有一只魔法喵 这只喵十分嗜睡 一睡就没有白天黑夜 喵喵一天可以睡多次 xff01 xff01 每次想睡多久
  • [区间DP/状压DP]Exercise Week12 A~E

    目录 A 水 找数题意样例样例输入 xff1a 样例输出 思路总结代码 B BFS 逃离题意样例样例输入 xff1a 样例输出 xff1a 思路总结代码 C DP 扫楼题意样例样例输入 xff1a 样例输出 思路总结代码 D 区间DP 最长
  • 新的开始( [USACO08OCT]打井Watering Hole)

    新的开始 newstart pas c cpp 题目描述 话说小 FF 在经历了上次 寻找古代王族遗产 的探险后 xff0c 成为了世界上最伟大的探险 家并拥有了一大笔财富 当然他不能坐吃山空 xff0c 必须创造财富 xff01 xff0
  • UOS配置本地APT源和外部软件包

    root 64 skill PC mount dev sr0 mnt mount mnt WARNING device write protected mounted read only root 64 skill PC vi etc ap
  • [二分答案] 洛谷P1873 砍树

    目录 题意样例样例输入 xff1a 样例输出 思路总结代码 题意 伐木工人米尔科需要砍倒M米长的木材 这是一个对米尔科来说很容易的工作 xff0c 因为他有一个漂亮的新伐木机 xff0c 可以像野火一样砍倒森林 不过 xff0c 米尔科只被
  • [区间DP]洛谷P1063 能量项链

    目录 题意样例样例输入 xff1a 样例输出 思路总结代码 题意 样例 样例输入 xff1a 4 2 3 5 10 样例输出 710 思路 1 经典区间DP题 算是合并石子的变种 只不过由一个点变成了一个区间 不过我们也可以用结构体存储 当
  • Linux命令行初接触-1 操作文件和目录

    操作文件 amp 目录 1 通配符含义常用通配符常用字符类类型匹配范例 2 mkdir 创建目录3 cp 复制文件和目录工作方式常用选项 4 mv 移动和重命名文件工作方式常用选项 5 rm 删除文件和目录工作方式常用选项注意事项 6 ln
  • 机器学习入入入入门(1)机器学习基本概念、引出深度学习

    机器学习入入入入门 xff08 1 xff09 0 前言1 基本步骤2 基本概念2 1 Hyperparameters2 2 local minima 3 linear model3 1 基础概念 4 piecewise linear cu
  • 深度学习蒟蒻入门——从0安装pytorch(CPU版)

    从0安装pytorch 1 检查自己的电脑有没有GPU2 安装CPU版的pytorch3 测试pytorch 1 检查自己的电脑有没有GPU 首先打开任务管理器 xff0c 选择性能栏 然后滑到最下 xff0c 看是否有GPU一项 xff0
  • 系统学习iOS动画 —— Stroke和路径动画

    这是要完成的动画 xff1a 先添加需要的代码 xff0c 这里需要将storyboard的ViewController换成TableViewController xff0c 将Under Top Bars 和 Under Bottom B
  • 不知道这些网站还做什么程序员呀!

    今天我就来总结一些程序员必备的网站 xff0c 囊括开源项目 解决bug 技术分享 一线资源和自我提升的网站 xff0c 希望能对广大程序猿有所帮助 xff0c 赶紧给我收藏起来 xff0c 下次刷不到了可别说我没提醒你 我们首先来看一下国
  • (音视频开发)WebRTC进阶流媒体服务器开发-多人互动架构

    一 xff1a 多人互动架构方案 xff08 一 xff09 WebRTC回顾 xff0c 两层含义 xff1a 1 WebRTC是google开源的流媒体客户端 xff0c 可以进行实时通讯 xff0c 主要应用于浏览器之间进行实时通讯
  • 10种linux下磁盘快照方式恢复系统

    导读大家都知道windows系统有一个磁盘快照的功能 xff0c 在windows2003中系统恢复开始依赖于一个叫做硬盘快照服务 Volume Snapshot Service 的服务 xff0c 他能够自动创建系统快照 包括正在使用的文
  • ubuntu安装go开发环境

    一 为ubuntu20 04更新源 给root用户设置密码 xff1a 命令 xff1a sudo passwd root 备份原来的源 xff0c 命令 xff1a sudo cp etc apt sources list etc apt
  • 如何修复Ubuntu中包缓存文件被毁问题

    导读今天 xff0c 我尝试更新我的 Ubuntu 18 04 LTS 的仓库列表 xff0c 但收到了一条错误消息 xff1a E The package cache file is corrupted it has the wrong
  • 1002 A+B for Polynomials (25分) 详解+易错点

    注意点 xff1a 系数为0 xff0c 则不输出 xff0c 例 xff1a 其中 1和1相加为0 xff0c 则在输出时避免这一项 xff0c 而且要注意结果的K值 xff0c 不要包括这一项 xff0c 思路 xff0c 利用结构体存
  • Linux远程桌面的选择

    Linux的远程桌面主要分两个部分 xff1a Linux客户机连Linux服务器和Windows客户机连Linux服务器 xff0c 还有现在用平板电脑连远程桌面 Linux客户机连Windows服务器比较简单没啥可说的 xff0c rd
  • Kali Linux mdk3WiFi洪水攻击 攻击路由器 生成虚假WiFi WiFi身份验证攻击可使连接WiFi的手机掉线重连抓包

    将无线网卡转换为监听模式 airmon ng start wlan0 查找附近无线网络 airodump ng wlan0mon Authentication DoS xff1a xff08 洪水攻击 xff0c 又叫做身份验证攻击 xff
  • 大一java程序设计的某次作业题解

    题目描述 xff1a 设计程序实现输入日期及机票张数 xff0c 计算出应付金额 假设北京至上海的机票全价为 1200 元 张 xff0c 以 2017 年为例进行程序编写 xff0c 所有的法定假日 xff0c 机票无折扣 xff1b 除

随机推荐