Unity高效双向滑动列表实现:循环列表与原生ScrollRect的融合方案
1. 项目概述在Unity UI开发中滑动列表Scroll View是构建内容展示界面的核心组件。无论是游戏中的背包、排行榜还是应用中的商品列表、聊天记录都离不开它。然而当需求从简单的单向滑动升级为“双向滑动”时——比如一个既能上下滚动查看条目又能左右滑动切换标签或查看详情的界面——很多开发者就会遇到性能卡顿、滑动冲突、逻辑混乱的“深水区”。网上能找到的解决方案要么过于简单粗暴性能堪忧要么封装成黑盒插件出了问题无从调试。今天我就结合自己踩过的无数个坑来聊聊如何从原理到实践亲手打造一个既高效又丝滑的双向滑动列表。我们不止要实现功能更要追求在移动设备上稳定60帧的流畅体验。这个方案的核心思路是垂直方向采用动态循环列表来承载海量数据项水平方向则巧妙利用Unity原生的Scroll Rect来实现轻量级切换。下面我们就从设计思路开始一步步拆解。2. 核心设计思路与架构选型实现双向滑动听起来像是在一个Scroll View里再嵌套一个Scroll View但这恰恰是性能陷阱的开始。最直接的“嵌套Scroll Rect”方案虽然能快速实现双向滑动但会带来两个致命问题一是输入事件处理容易冲突经常出现想上下滑却触发了左右滑的尴尬情况二是当列表项数量稍多时即使有Mask遮罩所有被实例化的UI元素依然会参与绘制计算造成严重的性能开销在低端移动设备上直接卡成幻灯片。因此我们的设计必须分而治之根据两个方向的不同特性来采用不同的技术方案。2.1 垂直方向动态循环列表的必要性垂直列表通常用于展示主要的数据集合例如成百上千个任务、邮件或好友。如果为每一条数据都实例化一个UI项Item内存和CPU都将不堪重负。动态循环列表也称为对象池滚动列表是解决此问题的标准答案。它的工作原理就像一个“视觉窗口”我们只创建足够填满当前屏幕可视区域的Item实例比如10个将它们放入一个对象池中管理。当用户滚动时将滚动出屏幕的Item回收到池中并重新利用它们来显示即将进入屏幕的新数据。这样无论数据源有100条还是10000条屏幕上活动的UI元素数量始终保持恒定性能开销可控。注意自己从头实现一个健壮的循环列表需要处理大量边界情况如快速滑动、跳跃到指定位置、Item尺寸不均等。在项目中如果条件允许我强烈建议使用经过大量项目验证的第三方插件如Unity UI Extensions中的Recyclable Scroll Rect或EnhancedScroller。它们封装了大部分复杂逻辑能节省大量开发时间。本文为阐述原理会介绍核心实现思想。2.2 水平方向利用原生Scroll Rect的轻量切换水平滑动的需求往往不同于垂直列表。它可能用于切换有限的几个标签页Tab、查看一个条目的不同详情图片图集或者像某些设计中的横向子菜单。这类场景的特点是水平方向的项目数量通常有限几个到几十个且切换频率相对较低。在这种情况下使用Unity原生的Scroll Rect是更合适的选择。它开箱即用支持惯性滑动、弹性回弹并且与Unity的EventSystem完美集成处理触摸输入非常稳定。我们不需要为水平方向再做复杂的动态加载因为有限的几个Item对性能影响微乎其微。2.3 整体架构组合与通信最终的架构可以理解为一个垂直的循环列表作为主容器每个垂直列表的Item行内部包含一个水平的原生Scroll Rect作为子容器。外层垂直一个自定义的VerticalLoopScrollRect组件管理数据源和垂直方向Item的创建、回收与定位。内层水平每个垂直Item内部是一个标准的UnityScrollRect组件用于管理其内部的水平子项如Tab按钮、详情卡片等。输入协调这是关键。我们需要智能地判断用户的滑动意图是想要垂直滚动还是水平切换。通常的规则是当水平滑动距离大于垂直滑动距离时视为水平滑动并阻止事件向垂直列表传递反之亦然。这可以通过继承和重写ScrollRect的OnBeginDrag,OnDrag,OnEndDrag方法并比较eventData.delta的x和y分量来实现。3. 核心实现细节与代码剖析理解了架构我们开始深入代码层面。这里我会分模块讲解关键部分的实现逻辑和注意事项。3.1 垂直循环列表的核心实现我们首先定义一个通用的循环列表项接口和数据绑定方法。// 循环列表单项的接口 public interface ILoopScrollItem { // 初始化或数据更新时调用index是该项在总数据中的索引 void OnUpdateData(int index); } // 垂直循环滚动组件简化核心版 public class VerticalLoopScrollRect : ScrollRect { // 对象池存储可复用的Item private StackRectTransform itemPool new StackRectTransform(); // 当前活跃的Item列表键为数据索引 private Dictionaryint, RectTransform activeItems new Dictionaryint, RectTransform(); // Item的预制体 public RectTransform itemPrefab; // 数据总数 private int totalCount 0; // 每个Item的高度假设固定 private float itemHeight; // 内容区域的上边距 private float paddingTop; protected override void Start() { base.Start(); // 禁用原生的滚动我们自己控制内容位置和Item生成 this.movementType MovementType.Unrestricted; itemHeight itemPrefab.rect.height; // 计算内容区域初始高度这取决于你的布局 content.sizeDelta new Vector2(content.sizeDelta.x, totalCount * itemHeight paddingTop * 2); } // 设置数据源并初始化 public void SetData(int count) { totalCount count; RecycleAllItems(); UpdateContentSize(); UpdateVisibleItems(); } // 更新内容区域大小 private void UpdateContentSize() { float contentHeight totalCount * itemHeight paddingTop * 2; content.sizeDelta new Vector2(content.sizeDelta.x, contentHeight); } // 核心根据滚动位置更新可见Item private void UpdateVisibleItems() { // 1. 计算当前视口能显示的数据索引范围 float viewportTop -content.anchoredPosition.y - paddingTop; float viewportBottom viewportTop - viewport.rect.height; int startIndex Mathf.FloorToInt(viewportBottom / itemHeight); int endIndex Mathf.CeilToInt(viewportTop / itemHeight); startIndex Mathf.Clamp(startIndex, 0, totalCount - 1); endIndex Mathf.Clamp(endIndex, 0, totalCount - 1); // 2. 回收不再可见的Item Listint keysToRemove new Listint(); foreach (var kvp in activeItems) { if (kvp.Key startIndex || kvp.Key endIndex) { RecycleItem(kvp.Value); keysToRemove.Add(kvp.Key); } } foreach (int key in keysToRemove) activeItems.Remove(key); // 3. 创建或更新当前可见的Item for (int i startIndex; i endIndex; i) { if (!activeItems.ContainsKey(i)) { RectTransform item GetItemFromPool(); item.SetParent(content, false); // 计算Item位置 float yPos -paddingTop - i * itemHeight; item.anchoredPosition new Vector2(0, yPos); // 数据绑定 ILoopScrollItem itemScript item.GetComponentILoopScrollItem(); if (itemScript ! null) itemScript.OnUpdateData(i); activeItems[i] item; } } } // 从对象池获取Item池空则实例化新对象 private RectTransform GetItemFromPool() { if (itemPool.Count 0) return itemPool.Pop(); return Instantiate(itemPrefab); } // 回收Item到对象池 private void RecycleItem(RectTransform item) { item.gameObject.SetActive(false); itemPool.Push(item); } private void RecycleAllItems() { /* 清空活跃列表并回收所有Item到池中 */ } // 在Update或ScrollRect的滚动回调中调用 public void OnValueChanged(Vector2 normalizedPos) { UpdateVisibleItems(); } }关键点解析MovementType.Unrestricted我们将原生的滚动类型设为无限制因为内容区域的高度是我们根据数据量虚拟出来的实际Item数量很少。真正的滚动感来源于我们不断更新Item位置和数据带来的视觉反馈。索引计算UpdateVisibleItems方法是心脏。它根据内容区域的当前锚点位置content.anchoredPosition和视口大小实时计算出哪些数据项应该出现在屏幕上。对象池itemPool和activeItems字典是性能保障。永远只实例化必要的UI对象。3.2 处理双向滑动冲突现在每个垂直Item内部可能都有一个水平的ScrollRect。我们需要让它们和平共处。创建一个中间组件来处理输入决策。public class BidirectionalScrollHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public ScrollRect verticalScrollRect; // 外层的垂直循环列表 public ScrollRect horizontalScrollRect; // 内层的水平滚动在每个Item上 private bool isDragging false; private Vector2 startDragPosition; // 滑动方向判定阈值像素可根据手感调整 public float directionThreshold 10f; public void OnBeginDrag(PointerEventData eventData) { isDragging true; startDragPosition eventData.position; // 同时通知两个ScrollRect开始拖动但后续可能只有一个真正处理 verticalScrollRect.OnBeginDrag(eventData); horizontalScrollRect.OnBeginDrag(eventData); } public void OnDrag(PointerEventData eventData) { if (!isDragging) return; Vector2 delta eventData.position - startDragPosition; // 判断主导滑动方向 if (Mathf.Abs(delta.x) Mathf.Abs(delta.y) directionThreshold) { // 水平滑动为主导阻止垂直滑动 horizontalScrollRect.OnDrag(eventData); verticalScrollRect.StopMovement(); // 停止垂直方向的惯性 } else if (Mathf.Abs(delta.y) Mathf.Abs(delta.x) directionThreshold) { // 垂直滑动为主导阻止水平滑动 verticalScrollRect.OnDrag(eventData); horizontalScrollRect.StopMovement(); } // 如果差值未超过阈值则暂时不处理等待更明确的滑动方向 } public void OnEndDrag(PointerEventData eventData) { isDragging false; // 根据最终的滑动趋势只让一个ScrollRect执行结束拖动逻辑主要是惯性计算 Vector2 finalDelta eventData.position - startDragPosition; if (Mathf.Abs(finalDelta.x) Mathf.Abs(finalDelta.y)) { horizontalScrollRect.OnEndDrag(eventData); verticalScrollRect.StopMovement(); } else { verticalScrollRect.OnEndDrag(eventData); horizontalScrollRect.StopMovement(); } } }将这个BidirectionalScrollHandler组件挂载到每个垂直Item的根节点上并为其分配对应的垂直和水平ScrollRect引用。它像一个交通警察根据初始滑动的向量差来决定本次拖动事件由谁来响应。实操心得directionThreshold这个阈值非常关键。设置得太小轻微斜向滑动就会导致方向误判设置得太大则需要非常笔直的滑动才能触发体验生硬。通常建议在5到20像素之间根据项目DPI和手感进行微调。最好的测试方法是在真机上反复滑动找到最自然的临界点。3.3 水平Scroll Rect的Item管理对于水平部分由于项目少我们可以采用简单直观的方法。假设每个垂直Item内部是几个Tab按钮。// 挂在水平Scroll Rect的Content下的子项上 public class HorizontalTabItem : MonoBehaviour { public Text titleText; public Image backgroundImage; private int tabIndex; private Actionint onTabClicked; public void Setup(int index, string title, Actionint clickCallback) { tabIndex index; titleText.text title; onTabClicked clickCallback; } // 由按钮触发 public void OnClick() { onTabClicked?.Invoke(tabIndex); // 可以在这里添加选中状态切换的视觉反馈 } }在垂直Item的数据绑定方法OnUpdateData中我们需要初始化其内部的水平Tab列表。public class VerticalListItem : MonoBehaviour, ILoopScrollItem { public ScrollRect horizontalScrollRect; public RectTransform tabContentRoot; public HorizontalTabItem tabPrefab; private ListHorizontalTabItem spawnedTabs new ListHorizontalTabItem(); public void OnUpdateData(int dataIndex) { // 假设根据dataIndex从数据管理器获取该行对应的Tab数据 TabData tabData DataManager.Instance.GetTabDataForRow(dataIndex); // 清理旧的Tab对象池管理更好这里简化 foreach (var tab in spawnedTabs) Destroy(tab.gameObject); spawnedTabs.Clear(); // 生成新的Tab for (int i 0; i tabData.tabNames.Count; i) { HorizontalTabItem tab Instantiate(tabPrefab, tabContentRoot); tab.Setup(i, tabData.tabNames[i], (clickedIndex) { Debug.Log($垂直行{dataIndex}的Tab {clickedIndex}被点击); // 处理Tab点击例如加载对应内容 }); spawnedTabs.Add(tab); } // 计算水平Content的宽度 float totalWidth tabData.tabNames.Count * (tabPrefab.GetComponentRectTransform().rect.width spacing); tabContentRoot.sizeDelta new Vector2(totalWidth, tabContentRoot.sizeDelta.y); // 重置水平滚动位置到第一个Tab horizontalScrollRect.horizontalNormalizedPosition 0; } }4. 性能优化与进阶技巧实现基本功能只是第一步要让列表真正“高效”和“丝滑”还需要在以下几个细节上下功夫。4.1 避免Canvas的频繁重建Unity UI的性能杀手之一就是Canvas的重建。当Canvas内的任何UI元素发生顶点变化位置、颜色、文本等时整个Canvas都需要重新生成网格Mesh这个过程称为“Rebuild”。对策1动静分离。将频繁变化的列表内容放在一个独立的Canvas下与背景、固定标题栏等静态UI分开。这样列表的滚动只会触发它所在Canvas的重建影响范围最小化。对策2使用CanvasGroup管理显隐。不要用SetActive(true/false)来显示/隐藏列表项这会导致Canvas重建。改用CanvasGroup通过将其alpha设为0和interactable、blocksRaycasts设为false来“隐藏”Item网格数据依然存在避免了重建。对策3合并Draw Call。确保列表项使用的图集Sprite Atlas尽可能少。所有Item使用同一张图集内的精灵可以极大减少Draw Call。Unity的UGUI默认会尝试合批但跨图集的元素会打断合批。4.2 循环列表的优化项Item尺寸不均上面的示例假设了固定高度的Item。如果Item高度不固定计算会复杂很多。你需要预先知道或计算每个索引Item的高度并维护一个“前缀和”数组以便快速计算任意索引Item的起始位置。这会显著增加复杂度也是很多开源循环列表库的核心难点。跳跃Jump功能直接跳转到列表第N项。你需要计算出目标项大概的归一化滚动位置然后瞬间将内容定位到那里并立即调用UpdateVisibleItems。注意要处理好跳转时的动画或缓动避免视觉上的突兀。数据更新当数据源发生变化增、删、改时如何高效更新列表对于循环列表不能简单重设数据因为当前显示的Item索引可能已经偏移。通常需要计算数据变化前后的差异最小化Item的刷新操作。4.3 内存与对象池深度优化我们之前用了简单的StackRectTransform作为对象池。在生产环境中这还不够。池化策略可以设计一个“温热”池和“冰冷”池。“温热”池保留最近回收的、数量有限的Item比如最多20个以备立即复用。“冰冷”池则存放多余的Item在内存压力大时可以被Unity的Resources.UnloadUnusedAssets清理掉。预加载在列表初始化前预先实例化并池化一定数量的Item如屏幕可显示数量的2倍可以避免在滚动时因瞬时实例化对象造成的卡顿。组件复用如果Item结构复杂包含大量子组件Image, Text等实例化开销很大。确保预制体已经引用好所有必要组件避免运行时GetComponent。5. 常见问题与实战调试记录在实际开发中你一定会遇到下面这些问题。这里是我的排查笔记。5.1 滑动卡顿特别是快速滑动时可能原因1OnValueChanged调用过于频繁。ScrollRect的onValueChanged事件在每一帧滚动时都会触发如果UpdateVisibleItems逻辑很重就会卡顿。解决不要直接在onValueChanged上绑定方法。可以改为在Update中根据时间间隔或滚动速度阈值来有选择地调用更新逻辑。或者使用协程在滚动开始后延迟几毫秒再执行密集计算。可能原因2Canvas重建。如上所述检查是否因UI元素显隐导致了Canvas重建。使用Frame Debugger工具查看每一帧的Canvas.SendWillRenderCanvases调用。可能原因3物理或逻辑更新在UI线程阻塞。确保没有在UI线程进行复杂的计算、同步加载资源或阻塞性IO操作。5.2 滑动结束时Item位置错乱或闪烁可能原因惯性滚动结束时content.anchoredPosition可能不是一个整数像素值导致计算出的起始索引startIndex出现小数取整问题进而使即将进入屏幕的Item在“显示-回收-显示”之间快速振荡。解决在滚动停止或速度低于某个阈值时对content.anchoredPosition进行一次“对齐”操作使其恰好停在一个Item的边界上。这可以通过修改ScrollRect的减速decelerationRate或重写其惯性计算逻辑来实现也可以监听滚动结束事件后进行位置微调。5.3 点击事件不响应或响应错误Item可能原因1Raycast遮挡。循环列表中的Item是复用的它的点击事件可能还绑定着旧的数据索引。在OnUpdateData中更新数据时一定要同步更新按钮点击事件回调中的索引参数。可能原因2BidirectionalScrollHandler吞掉了点击事件。我们的方向判断是在OnBeginDrag之后如果用户只是轻点tap也会触发OnBeginDrag但delta很小。需要区分点击和拖动。解决在OnEndDrag中判断总的拖动距离如果小于一个极小值如5像素则视为点击并手动触发当前指针位置下UI元素的点击事件。5.4 在真机上特别是iOS感觉不跟手可能原因输入采样率或惯性曲线与原生应用感觉不同。Unity的ScrollRect默认参数是为通用场景设计的。解决仔细调整ScrollRect的decelerationRate减速速率iOS上可以调低一点如0.13、elasticity弹性和scrollSensitivity滚动灵敏度。这些参数没有标准答案需要针对目标平台反复测试手感最好能对标流行的原生应用如微信、微博的列表滑动感觉。6. 扩展思考更复杂的交互与渲染方案当基础的双向滑动满足需求后我们可能会面临更高级的需求。6.1 与Unity UI Toolkit的对比Unity 2021 LTS之后UI Toolkit逐渐成熟。对于复杂的、数据驱动的列表UI Toolkit的ListView和GridView原生支持虚拟化即循环列表性能理论上更优且与Unity的样式系统、数据绑定集成更好。如果你的项目是新项目且UI复杂度高值得评估迁移到UI Toolkit的成本与收益。但对于大量已有UGUI代码和资产的项目改造UGUI的循环列表仍是更务实的选择。6.2 集成动画与特效丝滑的体验离不开动画。可以为Item的进入、退出添加渐隐、缩放或位置偏移动画。注意这些动画必须高效最好使用CanvasGroup修改Alpha或使用RectTransform的DOAnchorPos、DOScale等如果使用DOTween插件来实现避免每帧通过Update修改属性导致Canvas重建。6.3 分帧加载与异步操作如果每个Item需要从网络加载图片或复杂数据绝对不能同步进行。应该在Item进入视野时发起一个异步加载请求。加载过程中显示占位图加载完成后替换。同时要做好加载请求的管理当Item被快速滚动出屏幕时要取消未完成的加载请求避免无效操作和资源浪费。实现一个高效的双向滑动列表就像搭积木需要把事件处理、渲染效率、内存管理和用户体验这些“积木”严丝合缝地拼接在一起。它没有唯一的正确答案但遵循“分而治之”和“按需加载”的核心原则总能找到适合你项目当前阶段的最佳实践。上面的方案和代码是一个坚实的起点你可以根据实际遇到的具体问题在这些骨架上填充血肉最终打磨出体验流畅的列表组件。记住性能优化是一个持续的过程永远要在真机上测试用数据Profiler说话。

相关新闻

10分钟搭建企业级审批系统:FlowLong快速部署与配置指南

10分钟搭建企业级审批系统:FlowLong快速部署与配置指南

10分钟搭建企业级审批系统:FlowLong快速部署与配置指南 【免费下载链接】flowlong 飞龙工作流 FlowLong workflow🐉 真正的国产工作流引擎、json 格式实例模型、仿飞书钉钉审批流程设计器、🚩为中国特色审批匠心打造❗ 项目地址: https://g…

2026/10/18 4:00:38 阅读更多 →
让Windows桌面“活“起来:Lively动态桌面壁纸完全指南

让Windows桌面“活“起来:Lively动态桌面壁纸完全指南

让Windows桌面"活"起来:Lively动态桌面壁纸完全指南 【免费下载链接】lively Free and open-source software that allows users to set animated desktop wallpapers and screensavers powered by WinUI 3. 项目地址: https://gitcode.com/gh_mirrors/…

2026/10/19 7:43:37 阅读更多 →
如何永久备份微信聊天记录:WeChatMsg完整指南与数据守护方案

如何永久备份微信聊天记录:WeChatMsg完整指南与数据守护方案

如何永久备份微信聊天记录:WeChatMsg完整指南与数据守护方案 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we…

2026/10/18 4:00:51 阅读更多 →

最新新闻

图表设计实战:从能看到好用的数据可视化方法论

图表设计实战:从能看到好用的数据可视化方法论

1. 从“diagram-design”这个标题能读出什么第一次看到“diagram-design”这个标题,很多人可能会觉得信息量太少——没有副标题,没有技术栈说明,没有场景限定,就一个连字符拼起来的词组。但恰恰是这种极简的命名方式,反…

2026/10/19 8:34:18 阅读更多 →
open-code-review实战:从工具选型到团队落地的代码审查优化指南

open-code-review实战:从工具选型到团队落地的代码审查优化指南

1. 为什么“open-code-review”值得单独拿出来聊第一次听到“open-code-review”这个词,很多人会下意识觉得它只是“代码审查”的又一个新包装。但真正在团队里做过代码评审的人都知道,代码审查这件事,从来不是“看一眼代码有没有问题”这么简…

2026/10/19 8:34:18 阅读更多 →
数据增强实战指南:图像、文本与表格的增强方法与避坑经验

数据增强实战指南:图像、文本与表格的增强方法与避坑经验

开头,先把话说清楚:数据增强这四个字,我在不同项目里见过的待遇可以差出十万八千里。有人把它当成玄学,验证集过拟合了才想起来翻翻转转;有人把它当成万能药,不管表格还是文本一把梭,最后把分布…

2026/10/19 8:34:18 阅读更多 →
开源CLI代码评审工具:Git集成+LLM辅助的工程化实践

开源CLI代码评审工具:Git集成+LLM辅助的工程化实践

1. 项目概述:一个真正能落地的开源代码评审 CLI 工具“open-code-review”这个名字乍一听像某个 GitHub 上刚创建的冷门仓库,但如果你最近在团队里反复被问到“这次 PR 能不能自动过一遍逻辑漏洞?”“新同事提交的代码有没有硬编码密钥&#…

2026/10/19 8:34:18 阅读更多 →
图表设计方法论:从信息降噪到视觉层级的完整实践指南

图表设计方法论:从信息降噪到视觉层级的完整实践指南

1. 从"diagram-design"这个标题里能读出什么第一次看到"diagram-design"这个标题,我脑子里蹦出来的第一个念头是:这大概率不是一个单纯的"画图工具"项目,而是一套关于"图表设计"的方法论或者设计系统…

2026/10/19 8:34:18 阅读更多 →
Open-Code-Review:基于AST切片与LLM Agent的结构化代码评审范式

Open-Code-Review:基于AST切片与LLM Agent的结构化代码评审范式

1. “open-code-review”不是工具名,而是正在发生的协作范式迁移最近两周,我连续收到六位不同公司的技术负责人私信,问同一个问题:“你们团队用的 open-code-review 是哪个开源项目?GitHub 上搜不到稳定仓库。”——这…

2026/10/19 8:33:17 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →