本篇核心知识点:ScrollRect 滚动容器完整配置、Content 尺寸控制、Horizontal/Vertical 滑动开关、弹力 / 惯性 / 移动模式、自动隐藏滚动条、GridLayout 网格布局、动态生成列表 Item、NavMesh 导航网格安装、烘焙流程、NavMeshAgent 组件、自动寻路追击、静态烘焙弊端、A 星底层原理、寻路代码实现
一、ScrollRect 滚动视图容器
1 概念
ScrollRect 是 UGUI 组合滚动组件,搭配 Scrollbar 水平 / 竖直滚动条实现背包、商店、长文本等可滑动面板,配合 GridLayoutGroup 自动排列列表子物体,支持弹力回弹、惯性滑动、边界限制等交互效果。
2 特性 / 规则
-
Content 为滚动内容父物体,列表所有 Item 全部作为 Content 子物体;
-
Horizontal 控制左右滑动、Vertical 控制上下滑动,项目通常只勾选其中一项;
-
Movement Type 三种模式:Unrestricted 无边界可无限拖拽、Clamped 边界锁住拉不动、Elastic 带弹力回弹;
-
Inertia 惯性开关,松手后继续滑动一段距离;
-
Scroll Sensitivity 控制鼠标滚轮滑动速度;
-
Vertical/Horizontal Scrollbar 可设置自动隐藏,无滚动区域时隐藏滑块;
-
GridLayoutGroup 网格布局控制 Item 行列、尺寸、间距,自动排版无需手动调整位置。
3 语法 & 代码片段
动态生成列表 Item 核心片段
public GameObject itemPrefab;
public Transform content;
// 动态创建列表单元
void CreateItem(string name){
GameObject item = Instantiate(itemPrefab, content);
item.GetComponentInChildren<Text>().text = name;
}
4 相关知识点对比
Movement Type 三种模式区分
Unrestricted:无边界,拖拽无回弹,适合超长无边界内容;
Clamped:严格锁定内容边界,拖拽不会拉出面板,常规背包首选;
Elastic:拉出边界松手自动弹回,移动端界面常用柔和交互。
5 模块拓展
标准滚动列表搭建流程:新建 ScrollRect→设置 Content→挂载 GridLayoutGroup→调整单元格宽高间距→关闭多余滚动条→开启弹性回弹。
二、两道 UI 实战
1 进度条跳转场景
需求逻辑
使用 Slider 进度条模拟游戏加载,数值从 0 递增至 100 后自动切换目标场景,进度条视觉为模拟假加载,真实场景资源加载需异步接口配合。
代码
public Slider sd;
float _value = 0;
void Update(){
if (sd == null) return;
if (_value < 3f){
_value += Time.deltaTime;
sd.value = _value;
}
else{
SceneManager.LoadScene("work123");
}
}
2 动态滚动列表
一、核心概念
普通 ScrollView:所有 Item 全部实例化,数据上千条会卡顿、内存爆炸。
动态滚动列表(Virtual List) :只生成屏幕可视区域内少量 Item,滚动时复用现有 Item,修改数据,不新增 / 销毁物体,无论几万条数据都流畅。
常用两种:垂直滚动列表、水平滚动列表,UGUI 下基于 ScrollRect 实现。
二、底层核心原理
1. 数据与视图分离
数据源:数组 / 列表存所有数据(1000 条文本、图片等信息);
视图 Item:仅创建能铺满视口的少量预制体(比如屏幕同时显示 8 条,只实例化 8 个 Item);
视图数量公式:
显示Item数量 = 视口高度 ÷ 单个Item高度 + 2(缓冲Item,防止滚动空白)
2. 滚动监听
给 ScrollRect 绑定 OnValueChanged 事件,每次拖动 / 滚动实时获取滚动偏移量(content.anchoredPosition.y)。
根据偏移量计算:当前最顶部显示的是数据源第几条。
3. 复用逻辑(关键)
-
向上滚动:顶部 Item 滚出屏幕 → 移到底部,赋值下一组新数据;
-
向下滚动:底部 Item 滚出屏幕 → 移到顶部,赋值上一组旧数据;
全程不 Instantiate、不 Destroy,只是移动位置 + 刷新 UI 文字 / 图片。
4. 坐标计算逻辑(垂直列表举例)
-
单个 Item 固定高度 itemHeight;
-
滚动偏移 offsetY = scroll.content.anchoredPosition.y;
-
算出当前第一条数据索引:
startIndex = (int)(offsetY / itemHeight); -
遍历屏幕上所有 Item,分别绑定
startIndex、startIndex+1、startIndex+2...对应数据源; -
每个 Item 的锚点坐标:
y = -index * itemHeight;
三、完整执行流程
-
初始化
计算视口能容纳多少个 Item,批量生成对应数量预制体;
填充前 N 条数据,排列在 Content 中;
设置 Content 总高度 = 总数据条数 × 单个 Item 高度(撑开滚动区域)。
-
用户拖动滚动条 → ScrollRect 触发回调
-
获取滚动纵向偏移;
-
计算当前可见数据起始下标;
-
对比 Item 当前绑定的数据下标;
-
移出屏幕的 Item 直接平移到另一端,替换对应下标的数据源;
-
刷新 Item 上 Text/Image 显示内容。
-
-
循环复用
永远只有固定数量 Item,滚动只是换位置、换数据,物体总数不变。
四、优缺点对比
优点
-
极低内存:几百 / 上万条数据只十几个物体;
-
无 GC 卡顿:不频繁创建销毁物体;
-
加载速度快,无需一次性实例化全部条目。
缺点
-
要求 Item 高度统一(不规则高度动态列表计算复杂);
-
逻辑比普通 ScrollView 复杂,需要坐标、索引计算。
五、简易代码示意
public ScrollRect sv;
private GameObject ImgPrefab;
void Start(){
ImgPrefab = Resources.Load<GameObject>("Image");
StartCoroutine(Add());
}
IEnumerator Add(){
for(int i = 0; i < 10; i++){
// 拿到滚动列表的内容容器,所有列表条目必须放在 Content 下才能正常滚动
Transform content = sv.viewport.Find("Co ntent");
// Instantiate(预制体, 父物体, worldPositionStays):实例化物体并指定父级
// worldPositionStays:false 不保留世界坐标,强制使用父物体的局部坐标系,防止 UI 缩放、位置错乱(UGUI 必写)
GameObject item = Instantiate(ImgPrefab, content, false);
// 从刚创建的 item 身上获取 RectTransform 组件,后续用来调整尺寸和坐标
RectTransform rt = item.GetComponent<RectTransform>();
// 强制把这张图片的大小固定为宽 100、高 30,覆盖预制体原本的尺寸
rt.sizeDelta = new Vector2(100, 30);
yield return new WaitForSeconds(1f);
}
}
六、常见应用场景
聊天记录、商品列表、排行榜、背包道具、长文本分页、大量日志列表。
补充区分
-
静态 ScrollView:一次性生成所有 Item,少量数据使用;
-
动态虚拟滚动列表:海量数据必用;
-
对象池列表:和虚拟列表区别:对象池是创建缓存,滚动会频繁创建销毁,虚拟列表全程复用。
三、NavMesh 导航网格自动寻路系统
1 概念
Unity 内置寻路解决方案,底层基于 A * 算法,自动计算可行走区域、避开障碍物,实现 NPC 巡逻、怪物追击、玩家自动移动,高版本需手动安装 AI 导航包。
2 特性 / 规则
-
安装流程:PackageManager 搜索 AI Navigation 包,安装后重启引擎;
-
地面、墙体、障碍物必须勾选 Navigation Static 导航静态标记,烘焙后生成蓝色可行走区域;
-
蓝色区域代表可通行地面,障碍物无蓝色区域,寻路自动绕行;
-
NavMeshAgent 组件挂载需要移动的角色,提供速度、加速度、制动距离等参数;
-
核心函数 agent.SetDestination (目标坐标) 自动生成路径;
-
弊端:静态烘焙,场景障碍物、地面运行时修改后,寻路网格不会自动更新,必须重新烘焙;
-
怪物追击逻辑:Update 持续将玩家坐标设为目标点,实时更新路径追踪。
3 语法 & 代码片段
角色 / 怪物自动寻路、追击代码片段
using UnityEngine.AI;
public NavMeshAgent agent;
public Transform targetPlayer;
void Update(){
// 设置目标自动寻路
agent.SetDestination(targetPlayer.position);
}
4 完整烘焙操作步骤
-
选中地面、墙体、障碍物,勾选 Inspector 上方 Navigation Static;
-
打开 Window→AI→Navigation 导航窗口;
-
调整角色半径、高度、爬坡角度等烘焙参数;
-
点击 Bake 烘焙,场景生成蓝色可行走导航网格;
-
场景运行前保存生成的导航数据文件。
5 相关知识点对比
静态烘焙 NavMesh VS 动态实时寻路
静态烘焙:性能极高,仅适配固定不变地图,动态障碍物失效;
动态寻路(高级 NavMesh):运行实时计算,性能开销大,开放世界项目使用。
6 模块拓展
-
巡逻逻辑:协程循环切换多个目标点,调用 SetDestination 往返移动;
-
寻路参数优化:调整 agent.speed 移动速度、angularSpeed 旋转速度;
-
面试考点:A * 寻路基础原理、NavMesh 烘焙缺陷、动态地图解决方案。
综合拓展
-
UI 开发完整流水线:Canvas 自适应配置→基础组件搭建→滚动列表 Grid 布局→动态生成 Item→交互逻辑代码绑定,全程禁止编辑器拖拽赋值。
-
寻路系统开发规范:静态场景开发前期统一烘焙导航,动态可破坏地图使用动态 NavMesh 组件;怪物追击逻辑统一放在 Update 实时刷新目标。
-
高频 Bug 排查清单
滚动列表 Item 重叠:检查 GridLayout 单元格 Size 与 Spacing 间距;
怪物原地不动寻路失败:确认物体勾选 Navigation Static、完成烘焙、NavMeshAgent 组件正常;
进度条不增长:确认协程正常开启,数值递增逻辑未卡死。
-
进阶拓展学习方向:异步场景加载 AsyncOperation、动态烘焙导航、UI 图集优化、ScrollRect 虚拟滚动列表。求职项目拓展:制作完整背包系统(动态列表 + Toggle 分类)、怪物自动追击 AI、游戏加载界面三大实战模块写入简历。