Unity 3D 笔记(八)ScrollRect 滚动视图、NavMesh 自动寻路系统

本篇核心知识点:ScrollRect 滚动容器完整配置、Content 尺寸控制、Horizontal/Vertical 滑动开关、弹力 / 惯性 / 移动模式、自动隐藏滚动条、GridLayout 网格布局、动态生成列表 Item、NavMesh 导航网格安装、烘焙流程、NavMeshAgent 组件、自动寻路追击、静态烘焙弊端、A 星底层原理、寻路代码实现

一、ScrollRect 滚动视图容器

1 概念

ScrollRect 是 UGUI 组合滚动组件,搭配 Scrollbar 水平 / 竖直滚动条实现背包、商店、长文本等可滑动面板,配合 GridLayoutGroup 自动排列列表子物体,支持弹力回弹、惯性滑动、边界限制等交互效果。

2 特性 / 规则

  1. Content 为滚动内容父物体,列表所有 Item 全部作为 Content 子物体;

  2. Horizontal 控制左右滑动、Vertical 控制上下滑动,项目通常只勾选其中一项;

  3. Movement Type 三种模式:Unrestricted 无边界可无限拖拽、Clamped 边界锁住拉不动、Elastic 带弹力回弹;

  4. Inertia 惯性开关,松手后继续滑动一段距离;

  5. Scroll Sensitivity 控制鼠标滚轮滑动速度;

  6. Vertical/Horizontal Scrollbar 可设置自动隐藏,无滚动区域时隐藏滑块;

  7. 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. 复用逻辑(关键)

  1. 向上滚动:顶部 Item 滚出屏幕 → 移到底部,赋值下一组新数据;

  2. 向下滚动:底部 Item 滚出屏幕 → 移到顶部,赋值上一组旧数据;

    全程不 Instantiate、不 Destroy,只是移动位置 + 刷新 UI 文字 / 图片。

4. 坐标计算逻辑(垂直列表举例)

  1. 单个 Item 固定高度 itemHeight;

  2. 滚动偏移 offsetY = scroll.content.anchoredPosition.y;

  3. 算出当前第一条数据索引:startIndex = (int)(offsetY / itemHeight)

  4. 遍历屏幕上所有 Item,分别绑定 startIndex、startIndex+1、startIndex+2... 对应数据源;

  5. 每个 Item 的锚点坐标:y = -index * itemHeight

三、完整执行流程
  1. 初始化

    计算视口能容纳多少个 Item,批量生成对应数量预制体;

    填充前 N 条数据,排列在 Content 中;

    设置 Content 总高度 = 总数据条数 × 单个 Item 高度(撑开滚动区域)。

  2. 用户拖动滚动条 → ScrollRect 触发回调

    1. 获取滚动纵向偏移;

    2. 计算当前可见数据起始下标;

    3. 对比 Item 当前绑定的数据下标;

    4. 移出屏幕的 Item 直接平移到另一端,替换对应下标的数据源;

    5. 刷新 Item 上 Text/Image 显示内容。

  3. 循环复用

    永远只有固定数量 Item,滚动只是换位置、换数据,物体总数不变。

四、优缺点对比

优点

  1. 极低内存:几百 / 上万条数据只十几个物体;

  2. 无 GC 卡顿:不频繁创建销毁物体;

  3. 加载速度快,无需一次性实例化全部条目。

缺点

  1. 要求 Item 高度统一(不规则高度动态列表计算复杂);

  2. 逻辑比普通 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);
    }
}
六、常见应用场景

聊天记录、商品列表、排行榜、背包道具、长文本分页、大量日志列表。

补充区分
  1. 静态 ScrollView:一次性生成所有 Item,少量数据使用;

  2. 动态虚拟滚动列表:海量数据必用;

  3. 对象池列表:和虚拟列表区别:对象池是创建缓存,滚动会频繁创建销毁,虚拟列表全程复用。

三、NavMesh 导航网格自动寻路系统

1 概念

Unity 内置寻路解决方案,底层基于 A * 算法,自动计算可行走区域、避开障碍物,实现 NPC 巡逻、怪物追击、玩家自动移动,高版本需手动安装 AI 导航包。

2 特性 / 规则

  1. 安装流程:PackageManager 搜索 AI Navigation 包,安装后重启引擎;

  2. 地面、墙体、障碍物必须勾选 Navigation Static 导航静态标记,烘焙后生成蓝色可行走区域;

  3. 蓝色区域代表可通行地面,障碍物无蓝色区域,寻路自动绕行;

  4. NavMeshAgent 组件挂载需要移动的角色,提供速度、加速度、制动距离等参数;

  5. 核心函数 agent.SetDestination (目标坐标) 自动生成路径;

  6. 弊端:静态烘焙,场景障碍物、地面运行时修改后,寻路网格不会自动更新,必须重新烘焙;

  7. 怪物追击逻辑:Update 持续将玩家坐标设为目标点,实时更新路径追踪。

3 语法 & 代码片段

角色 / 怪物自动寻路、追击代码片段

复制代码
using UnityEngine.AI;
public NavMeshAgent agent;
public Transform targetPlayer;
void Update(){
    // 设置目标自动寻路
    agent.SetDestination(targetPlayer.position);
}

4 完整烘焙操作步骤

  1. 选中地面、墙体、障碍物,勾选 Inspector 上方 Navigation Static;

  2. 打开 Window→AI→Navigation 导航窗口;

  3. 调整角色半径、高度、爬坡角度等烘焙参数;

  4. 点击 Bake 烘焙,场景生成蓝色可行走导航网格;

  5. 场景运行前保存生成的导航数据文件。

5 相关知识点对比

静态烘焙 NavMesh VS 动态实时寻路

静态烘焙:性能极高,仅适配固定不变地图,动态障碍物失效;

动态寻路(高级 NavMesh):运行实时计算,性能开销大,开放世界项目使用。

6 模块拓展

  1. 巡逻逻辑:协程循环切换多个目标点,调用 SetDestination 往返移动;

  2. 寻路参数优化:调整 agent.speed 移动速度、angularSpeed 旋转速度;

  3. 面试考点:A * 寻路基础原理、NavMesh 烘焙缺陷、动态地图解决方案。

综合拓展

  1. UI 开发完整流水线:Canvas 自适应配置→基础组件搭建→滚动列表 Grid 布局→动态生成 Item→交互逻辑代码绑定,全程禁止编辑器拖拽赋值。

  2. 寻路系统开发规范:静态场景开发前期统一烘焙导航,动态可破坏地图使用动态 NavMesh 组件;怪物追击逻辑统一放在 Update 实时刷新目标。

  3. 高频 Bug 排查清单

    滚动列表 Item 重叠:检查 GridLayout 单元格 Size 与 Spacing 间距;

    怪物原地不动寻路失败:确认物体勾选 Navigation Static、完成烘焙、NavMeshAgent 组件正常;

    进度条不增长:确认协程正常开启,数值递增逻辑未卡死。

  4. 进阶拓展学习方向:异步场景加载 AsyncOperation、动态烘焙导航、UI 图集优化、ScrollRect 虚拟滚动列表。求职项目拓展:制作完整背包系统(动态列表 + Toggle 分类)、怪物自动追击 AI、游戏加载界面三大实战模块写入简历。

相关推荐
sugar__salt19 小时前
Vue3 基础知识点整理 —— 从入门到响应式核心完全指南
vue.js·笔记·vue·vue3
凉、介19 小时前
Virtio(三):Virtqueue 建立与 Buffer 提交
笔记·学习·嵌入式·arm·虚拟化·virtio
三水不滴19 小时前
RAG 评测数据集,到底该怎么准备?
经验分享·笔记
极客侃科技20 小时前
如何把真人动作迁移到3D角色上?用V2Fun完成视频动捕和动作应用
3d
Lhappy嘻嘻20 小时前
网络(四)|全网最细网络层原理:IP 协议、IP 地址分类、子网划分、路由转发、NAT 穿透详解
java·笔记·网络协议·计算机网络
鱼子星_20 小时前
【C++】vector
开发语言·c++·笔记·stl
吃着火锅x唱着歌20 小时前
Effective C++ 学习笔记 条款38 通过复合塑模出has-a或“根据某物实现出”
c++·笔记·学习
syagain_zsx20 小时前
库制作与原理 · 链接知识笔记
c语言·c++·笔记·动态库·静态库
caimouse21 小时前
mm学习笔记_04:VAD树算法与地址空间分配
笔记·学习·算法·reactos