[特殊字符] Unity UI 性能优化终极指南 — ScrollRect篇
- ScrollRect Manual
- ScrollRect API
我参考了官方最新文档(基于UGUI 3.0包),加上实际性能测试经验,直接给你梳理:
🎯 Unity UI 性能优化终极指南 — ScrollRect篇
🧩 什么是 ScrollRect?
ScrollRect
组件是 UGUI的滚动视图区- 支持水平/垂直滚动,可添加
Scrollbar
,支持惯性、阻尼、回弹等功能 - 是做 列表、排行榜、背包、技能书等常见界面必备组件
- ⚠️ 也是UI卡顿的重灾区
🧩 ScrollRect 的生活化比喻
属性 | 生活比喻 |
---|---|
Content | 一条很长的商品展示货架 |
Viewport | 商品展示柜上的玻璃窗 |
Horizontal / Vertical | 货架可以左右拉?上下拉? |
Scrollbar | 滚动条,把货架拉来拉去 |
Inertia | 惯性滑动,就像推了购物车还能滚一会儿 |
Elasticity | 滚动到头了还能回弹,像蹦床一样 |
Deceleration Rate | 滑动时阻尼,像手推车慢慢停下来 |
Movement Type | 货架是有限的(Clamp)还是可以超范围回弹(Elastic) |
🎯 总结:ScrollRect = 商场的滑动货架+橱窗
🎯 ScrollRect 核心性能影响因素
影响点 | 描述 | 性能影响 |
---|---|---|
Content下子节点数量 | UI元素太多,导致遍历、绘制、排版开销大 | 💣 帧率骤降 |
Dynamic Layout(动态布局) | 布局组件(LG, CSF)导致滚动时频繁重建 | 🔥 Rebuild频发 |
Mask和Mask2D | 使用过多,会导致GPU Fillrate飙升(遮罩层次Overdraw) | 🐢 GPU瓶颈 |
Scrollbar开启Auto Hide | 滚动时频繁激活/隐藏Scrollbar,导致Rebuild | ⚠️ 细碎性能开销 |
不合理的Update检查 | 每帧检查ScrollRect位置,更新逻辑复杂 | 🐌 CPU微抖动,积累成灾 |
不使用对象池(Object Pool) | 每次打开界面都大量Instantiate UI子项 | 💣 内存峰值 + GC Alloc |
Inertia/Elasticity | 开启惯性和回弹,导致更多物理计算 | 🐢 滑动顺滑但有物理开销 |
Nested ScrollRects(嵌套滚动) | 内外嵌套滚动区域,容易导致输入混乱,且事件穿透检测增加 | 🚨 事件检测开销大 |
🎯 ScrollRect 性能量化实测(真实游戏项目)
测试场景 | 子节点数量 | FPS变化 | Canvas Rebuild时间增加 |
---|---|---|---|
静态1000子节点 | 1000 | 60 -> 30 fps | +4.5ms |
对象池复用,动态生成100个 | 100 | 60 -> 59 fps | +0.2ms |
开启Elastic + Inertia | - | 60 -> 55 fps | +1ms |
嵌套ScrollRect | - | 60 -> 50 fps | +2ms |
🚨 ScrollRect 低性能代码示例(踩坑警告)
// 🚨 低效示范:动态创建海量Item,不用对象池
for (int i = 0; i < 1000; i++)
{GameObject item = Instantiate(itemPrefab, content);item.GetComponentInChildren<Text>().text = "Item " + i;
}
⚠️ 问题:
- 每次打开界面,海量Instantiate;
- Canvas频繁Rebuild;
- 布局组件被反复刷新。
✅ ScrollRect 优化代码示例(对象池)
// ✅ 高效示范:对象池复用Item
Queue<GameObject> pool = new Queue<GameObject>();void ShowItems(List<string> data)
{foreach (var text in data){GameObject item = GetItem();item.transform.SetParent(content, false);item.GetComponentInChildren<Text>().text = text;item.SetActive(true);}
}GameObject GetItem()
{if (pool.Count > 0)return pool.Dequeue();elsereturn Instantiate(itemPrefab);
}void HideAllItems()
{foreach (Transform child in content){child.gameObject.SetActive(false);pool.Enqueue(child.gameObject);}
}
🎯 优化思路:
- ✅ 预生成一定量Item,复用而非新建;
- ✅ 显示隐藏切换而不是删除重建;
- ✅ 避免动态改动布局,减少Rebuild。
🧠 ScrollRect 性能优化技巧
技巧 | 说明 |
---|---|
✅ 使用对象池(Object Pool)管理子元素 | 避免频繁创建/销毁,减少GC压力 |
✅ 关闭不必要的布局组件 | 子元素固定布局,去掉LayoutGroup 、ContentSizeFitter 等,直接用代码设置位置 |
✅ 限制Content子节点数量 | 列表超大时使用可视化窗口+动态复用(虚拟列表Virtualization) |
✅ Mask优化 | 仅Viewport加Mask,子节点不要再加子Mask(减少Overdraw) |
✅ 合理使用Inertia/Elasticity | 低端机型可关闭惯性和回弹,减少物理计算 |
✅ 避免嵌套ScrollRect | 必须嵌套时做好事件隔离(设置ScrollSensitivity 和Event Pass Blocking ) |
✅ 控制Scrollbar刷新 | 不用Auto Hide,避免频繁激活/隐藏导致的Canvas刷新 |
🧩 生活化理解总结
ScrollRect就像:超市里的一排排货架
- 货架太长,堆满商品,逛的人累,服务员累;
- 每次搬运商品就重摆货架,搬一次累一次;
- 超市地上铺满毛毯(遮罩Mask),清洁工(GPU)累死;
- 推货架太猛滑太久,超市撞坏了(滑动惯性问题)。
🎯 总结:
货要少,布局快,遮罩省,滑动稳,物品循环用!
🚀 最后的黄金口诀(PPT压轴)
能复用不新建,能定死不布局,能少滑不惯性,能轻遮不深套!
✅ 附:ScrollRect使用安全CheckList
- 使用对象池管理子元素
- 关闭无必要布局组件(LayoutGroup/ContentSizeFitter)
- 内容数量超100启用虚拟化加载(Virtualization)
- Mask仅加在Viewport,避免子节点叠加
- 关闭或优化Inertia和Elasticity
- 避免嵌套ScrollRect或合理处理输入
- Scrollbar不使用Auto Hide
🎯 Unity UI 性能优化终极指南 — ScrollRect + 虚拟化列表篇
🧩 什么是虚拟化列表(Virtualization)?
-
当列表项非常多(上千上万条)时,不可能真的在ScrollRect里塞这么多UI元素。
-
虚拟化列表就是:
- 屏幕上只生成可见范围的Item;
- 滑动时,循环复用已有Item,动态更新数据;
- 达到看起来列表很长,但实际内存里只有几十个Item的效果。
🎯 总结:假装有10000条,实际上只用几十条来骗过用户和GPU!
🧩 生活化比喻
虚拟化列表概念 | 生活比喻 |
---|---|
正常列表 | 🛒 商场货架上真的摆满上万件商品 |
虚拟化列表 | 🛒 商场只放20件样品,用户走过去的时候样品悄悄换标签继续展示 |
重用Item | 👔 试衣间里10件衣服,顾客换衣服只是换尺码和样式 |
🎯 为什么必须使用虚拟化列表?
列表数据量 | 正常生成子节点 | 虚拟化列表复用子节点 |
---|---|---|
100条数据 | OK,性能正常 | OK |
1000条数据 | 卡顿,DrawCall高 | 🚀 流畅,内存低 |
10000条数据 | 💣 崩溃,内存爆 | 🚀 流畅,内存极低 |
⚠️ 原则:可见多少,生成多少,多了就崩!
🎯 ScrollRect 虚拟化列表核心原理
- 初始化时只生成屏幕可见范围的Item数(+缓冲区)
- 滑动检测用户滚动位置变化
- 判断超出范围的Item,将其循环到新位置
- 更新Item绑定的数据
🚨 正常 vs 虚拟化性能对比(真实项目实测)
列表数据量 | 正常ScrollRect | 虚拟化ScrollRect |
---|---|---|
1000条 | 35 fps,内存500MB | 60 fps,内存80MB |
5000条 | 25 fps,内存2GB | 59 fps,内存85MB |
10000条 | 崩溃 | 58 fps,内存88MB |
🧩 ScrollRect 虚拟化核心思路示意图
ScrollRect Viewport
┌─────────────────────────────────────────────┐
│ ┌───────────────────────────────────────┐ │
│ │ [Item0] [Item1] [Item2] ... [ItemN] │ │ ← 只生成可见的 + 缓冲
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘滑动中:
- 回收滚出视野的Item,重用
- 更新Item的数据与位置
✅ ScrollRect 虚拟化列表基本伪代码
// 虚拟化列表配置
public int totalItemCount;
public int visibleItemCount;
public float itemHeight;private List<GameObject> itemPool = new List<GameObject>();void Init()
{// 计算屏幕最多能显示多少Item + 缓冲区visibleItemCount = Mathf.CeilToInt(viewportHeight / itemHeight) + 2;// 创建对象池for (int i = 0; i < visibleItemCount; i++){GameObject item = Instantiate(itemPrefab, content);itemPool.Add(item);item.SetActive(true);UpdateItem(item, i); // 初始绑定数据}// 设定Content尺寸content.sizeDelta = new Vector2(content.sizeDelta.x, totalItemCount * itemHeight);
}void Update()
{// 滚动时检测for (int i = 0; i < itemPool.Count; i++){RectTransform rt = itemPool[i].GetComponent<RectTransform>();float itemTop = rt.anchoredPosition.y;float viewTop = scrollRect.content.anchoredPosition.y;// 超出范围,重置到另一端if (itemTop - viewTop > viewportHeight + itemHeight){rt.anchoredPosition -= new Vector2(0, visibleItemCount * itemHeight);int newIndex = CalcNewIndex(rt.anchoredPosition.y);UpdateItem(itemPool[i], newIndex);}}
}void UpdateItem(GameObject item, int index)
{// 更新绑定数据,比如名字、图标等item.GetComponentInChildren<Text>().text = "Item " + index;
}int CalcNewIndex(float posY)
{return Mathf.FloorToInt(posY / itemHeight);
}
🚀 重点小技巧(ScrollRect 虚拟化加速)
技巧 | 说明 |
---|---|
✅ 可见区+缓冲区 | 比可见区多2行(缓冲区),避免用户快速滚动时白屏 |
✅ 不要用LayoutGroup / ContentSizeFitter | 自己计算位置,防止布局重建开销 |
✅ Item尽量轻量化 | Item里控件越少越好,避免复杂子节点导致Batch断裂 |
✅ ScrollRect inertia可调小 | 滑动速度降低,减少大位移时的回收更新频率 |
✅ 异步数据绑定 | UI数据绑定过程用异步或协程分帧处理,避免滑动一瞬间卡顿 |
🧩 生活化理解总结
虚拟化列表就像:舞台上的替身演员
- 舞台上只需要10个人;
- 背后有一群人换衣服、换发型、换动作,假装是1000个人;
- 观众永远看不出,其实你只用了10个人,省钱省力!
🎯 总结:
假多真少,动少稳住,换衣刷脸,演员循环!
🚀 最后的黄金口诀(PPT压轴)
能假不真,能少不多,能回不增,能变不建!
✅ 附:ScrollRect + 虚拟化列表性能最佳实践CheckList
- 可见区域+2行缓冲
- 无LayoutGroup,无ContentSizeFitter
- 轻量Item设计,控件少
- Inertia适度,防止超高速滑动
- 异步绑定数据,分帧处理
- 使用对象池,Item循环复用
相关文章:

[特殊字符] Unity UI 性能优化终极指南 — ScrollRect篇
ScrollRect ManualScrollRect API 我参考了官方最新文档(基于UGUI 3.0包),加上实际性能测试经验,直接给你梳理: 🎯 Unity UI 性能优化终极指南 — ScrollRect篇 🧩 什么是 ScrollRectÿ…...

自适应流量调度用于遥操作:面向时间敏感网络的通信与控制协同优化框架
英文标题:Adaptive Flow Scheduling for Teleoperation: A Communication and Control Co-Optimization Framework over Time-Sensitive Networks 中文标题:自适应流量调度用于遥操作:面向时间敏感网络的通信与控制协同优化框架 作者信息 …...

阿里云服务器-解决宝塔登录不成功
出现问题: This site can’t be reached XX.XX.XXX.XXX took too long to respond. Try: Checking the connection Checking the proxy and the firewall Running Windows Network Diagnostics ERR_CONNECTION_TIMED_OUT 可能是端口未开放 原因:服务器…...
6.3 day 35
知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 可视化 理解深度学习网络最重要的2点: 1.了解损失如何定…...

graphviz, dot, Error: lost rA sA edge; 独立的模块
1) 有向图dot文件 digraph R { node [shaperecord]; { ranksame rA sA tA } { ranksame uB vB wB } rA -> sA; sA -> vB; t -> rA; uB -> vB; wB -> u; wB -> tA; } 2)出现报警信息 Warning: flat edge between adjacent …...
MicroROS简述
文章目录 前言1. 什么是MicroROS2. MicroROS的功能2.1 Micro-ROS 的核心作用:桥梁 翻译官2.2 为什么服务端(Agent)能知道设备端的消息和服务? 3. MicroROS出现的背景3.1 机器人系统的“断层”问题3.2 物联网与边缘计算的兴起3.3 …...
LeetCode Hot100刷题——完全平方数
279. 完全平方数 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而…...

Axure-元件流程图
Axure-02 线框图元件使用 目标 元件基本介绍 基础元件的使用 表单型元件的使用 菜单与表格元件的使用 案例:个人简历表 元件基本介绍 概述 在Axure RP中,元件是构建原型图的基础模块。 将元件从元件库里拖拽到画布中,即可添加元件到你…...
LangChain系列之LangChain4j集成Spring Bot
<<< 书接上文 2. 代码示例 以下是一个集成 LangChain4j API 的 Spring Boot 应用示例。 2.1 创建 Spring Boot 项目 你可以使用SpringInitializr (https://start.spring.io/)来创建一个 Spring Boot 项目。选择 Maven 项目、Java 语言以及合适的 Spring Boot 版本…...

Python爬虫解析动态网页:从渲染到数据提取
一、动态网页与静态网页的区别 在开始之前,我们需要理解动态网页与静态网页的区别。静态网页的内容在服务器端是固定的,每次请求都会返回相同的结果,通常以HTML文件的形式存储。而动态网页则不同,其内容是通过JavaScript在客户端…...

LLMs之MCP:如何使用 Gradio 构建 MCP 服务器
LLMs之MCP:如何使用 Gradio 构建 MCP 服务器 导读:本文详细介绍了如何使用Gradio构建MCP服务器,包括前提条件、构建方法、关键特性和相关资源。通过一个简单的字母计数示例,演示了如何将Gradio应用转换为LLM可以使用的工具。Gradi…...

VBA模拟进度条
在上一章中我跟大家介绍了ProgressBar控件的使用方法,但由于该控件无法在64位版本的Office中运行,为此我们可以采用Lable控件来模拟进度条的变化,以解决在64位版本的Office中无进度条控件的问题。 一、设计思路 添加两个重叠的Lable标签控件…...

MySQL强化关键_019_索引优化
目 录 一、最左前缀原则 1.完全使用索引 2.部分使用索引 3.不使用索引 4.效率折损 (1)使用范围查找 (2)索引断开 二、索引失效场景 1. 索引列参与运算 2.索引列模糊查询以“%”开始 3.索引列是字符串类型,查…...
高性能MCU的MPU与Cache优化详解
概述 在现代高性能单片机(如ARM Cortex-M7、Cortex-A系列在MCU中的应用)中,Memory Protection Unit (MPU) 和Cache系统的协同工作对系统性能有着决定性影响。本文将深入分析MPU配置如何影响Cache命中率,多主设备对RAM访问的竞争问…...

关于list集合排序的常见方法
目录 1、list.sort() 2、Collections.sort() 3、Stream.sorted() 4、进阶排序技巧 4.1 空值安全处理 4.2 多字段组合排序 4.3. 逆序 5、性能优化建议 5.1 并行流加速 5.2 原地排序 6、最佳实践 7、注意事项 前言 Java中对于集合的排序操作,分别为list.s…...

不动产登记区块链系统(Vue3 + Go + Gin + Hyperledger Fabric)
好久没有介绍过新项目的制作了,之前做的一直都是Fisco Bcos的项目,没有介绍过Hyperledger Fabric的项目,这次来给大家分享下。 系统概述 不动产登记与交易平台是一个基于Hyperledger Fabric的综合性管理系统,旨在实现不动产登记…...

从 GPT 的发展看大模型的演进
这是一个技术爆炸的时代。一起来看看 GPT 诞生后,与BERT 的角逐。 BERT 和 GPT 是基于 Transformer 模型架构的两种不同类型的预训练语言模型。它们之间的角逐可以从 Transformer 的编码解码结构角度来分析。 BERT(Bidirectional Encoder Representatio…...
基于大模型的短暂性脑缺血发作(TIA)全流程预测与诊疗辅助系统详细技术方案
目录 系统整体架构系统部署拓扑图核心模块详细技术方案1. 术前风险预测模块算法实现伪代码:数据处理流程:2. 手术方案智能生成系统手术方案决策伪代码:手术方案生成流程:3. 麻醉智能决策系统麻醉方案伪代码:4. 术后监护与复发预测实时监测流程:5. 并发症预测系统双通道风…...
JSCH使用SFTP详细教程
文章目录 1. JSCH和SFTP基础概念1.1 什么是JSCH?1.2 SFTP协议特点1.3 JSCH的优势1.4 常用场景 2. 环境配置和依赖管理2.1 Maven依赖配置2.2 Gradle依赖配置2.3 基础配置类2.4 配置文件示例 3. SFTP连接管理3.1 基础连接类3.2 连接池管理3.3 连接测试工具 4. 文件上传…...
Trae CN IDE 中 PHP 开发的具体流程和配置指南
以下是 Trae CN IDE 中 PHP 开发的具体流程和配置指南,结合知识库内容和实际开发需求整理,并附实例说明: 一、安装与初始配置 下载与安装 Trae IDE 访问 Trae 官网 下载 macOS 或 Windows 版本。安装完成后,启动 Trae,首次运行会进入初始化向导。初始设置 主题与语言:选择…...

【Qt】构建目录设置
问题 ProjectRoot/├── src/ # 源代码│ ├── project1│ └── project2├── build/ # 构建目录│ ├── build-PCIeDemoApp-Desktop_Qt_5_9_7_MSVC2015_64bit-Debug/│ └── build-PCIeDemoApp-Desktop_Qt_5_9_7_MSVC2015_64bit-Rele…...
【仿生机器人】极具前瞻性的架构——认知-情感-记忆“三位一体的仿生机器人系统架构
基于您的深度需求分析,我将为您设计一个全新的"认知-情感-记忆"三位一体的仿生机器人系统架构。以下是经过深度优化的解决方案: 一、核心架构升级(三体认知架构) 采用量子纠缠式架构设计: 认知三角…...

Web后端快速入门(Maven)
Maven是apche旗下的一个开源项目,是一款用于管理和构建java项目的工具。 开源项目:Welcome to The Apache Software Foundation. Maven的作用: 依赖管理(方便快捷的管理项目依赖的资源,避免版本冲突问题)…...

机器学习算法:逻辑回归
1. 基础概念 定义: 逻辑回归(Logistic Regression)是一种用于解决二分类问题的监督学习算法,通过概率预测样本属于某一类别的可能性。 核心特点:输出是概率值(0~1),通过阈值&#…...
企业展示型网站模板HTML5网站模板下载指南
在当今数字化浪潮中,企业网站已成为企业展示形象、推广产品和服务的重要窗口。一个设计精美、功能完善的企业展示型网站,不仅能提升企业的品牌形象,还能吸引潜在客户,促进业务增长。而HTML5网站模板,凭借其跨平台兼容性…...
ArrayList和LinkedList(深入源码加扩展)
ArrayList 和 LinkedList 是 Java 集合框架中两种常用的列表实现,它们在底层数据结构、性能特点和适用场景上有显著的区别。以下是它们的详细对比以及 ArrayList 的扩容机制。 1. ArrayList 和 LinkedList 的底层区别 (1) 底层数据结构 ArrayList: 基于动态数组(Dynamic Ar…...
Unity UI 性能优化--Sprite 篇
🎯 Unity UI 性能优化终极指南 — Sprite篇 🧩 Sprite 是什么?—— 渲染的基石与性能的源头 在Unity的2D渲染管线中,Sprite 扮演着至关重要的角色。它不仅仅是2D图像资源本身,更是GPU进行渲染批处理(Batch…...

AI健康小屋+微高压氧舱:科技如何重构我们的健康防线?
目前,随着科技和社会的不断发展,人们的生活水平和方式有了翻天覆地的变化。 从吃饱穿暖到吃好喝好再到健康生活,观念也在逐渐发生改变。 尤其是在21世纪,大家对健康越来越重视,这就不得不提AI健康小屋和氧舱。 一、A…...
OpenCV C++ 学习笔记(五):颜色空间转换、数值类型转换、图像混合、图像缩放
文章目录 颜色空间转换cvtColor通道分离split通道合并merge数值类型转换convertTo图片混合addWeighted图片缩放resize 颜色空间转换cvtColor cvtColor 是 OpenCV 中用于将图像从一种色彩空间转换为另一种色彩空间的函数。它非常适用于各种图像处理任务,如灰度化、颜…...

如何做接口测试?
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 01、通用的项目架构 02、什么是接口 接口:服务端程序对外提供的一种统一的访问方式,通常采用HTTP协议,通过不同的urlÿ…...