Unity3D游戏开发:自研Astar寻路系统核心实现与优化指南
1. 项目概述为什么我们需要一个自研的Astar寻路系统在Unity3D游戏开发里寻路是个绕不开的核心功能。无论是让NPC在开放世界里巡逻还是让RTS游戏里的单位集群移动甚至是解谜游戏中角色的智能移动背后都需要一个高效、可靠的寻路算法来驱动。Unity自带的NavMesh系统确实强大开箱即用对于大多数常规的3D场景来说已经足够。但当你遇到一些“非典型”需求时比如动态变化的网格地形、需要高度自定义的移动成本例如不同地形的移动速度惩罚、或者你想在2.5D等特殊视角下实现更精细的控制自研一套Astar寻路系统就成了一个必须掌握的技能。AstarA*算法本质上是一种在图形平面上寻找从起点到终点的最低成本路径的算法。它之所以在游戏开发中经久不衰是因为它在“最优解”和“搜索效率”之间取得了绝佳的平衡。它不像广度优先搜索BFS那样盲目也不像深度优先搜索DFS那样容易跑偏而是通过一个启发式函数Heuristic来“聪明地”引导搜索方向。自己动手实现它不仅能让你彻底吃透寻路的底层逻辑更能让你获得对游戏角色移动的完全掌控力。当你的游戏世界需要一些NavMesh无法轻易实现的“魔法”时这套自研系统就是你的魔法杖。2. 核心思路与架构设计从网格到路径要打造一个3D Astar系统我们不能一上来就埋头写算法。首先得把“舞台”搭好这个舞台就是寻路所依赖的“图”Graph。在3D游戏中最直观、最常用的图就是网格Grid。2.1 网格数据结构的构建网格的本质是一个二维数组数组中的每个元素代表世界中的一个“节点”Node。但这个节点不仅仅是空间中的一个点它需要携带丰富的状态信息。public class PathNode { public int x; // 网格X坐标 public int y; // 网格Y坐标在3D中这通常对应世界XZ平面 public Vector3 worldPosition; // 对应的世界坐标用于角色移动 public bool isWalkable; // 是否可通行 public int movementPenalty; // 移动惩罚值例如沼泽地惩罚高道路惩罚低 public int gCost; // 从起点到当前节点的实际代价 public int hCost; // 从当前节点到终点的预估代价启发值 public int fCost { get { return gCost hCost; } } // 总代价 public PathNode cameFromNode; // 路径回溯指针指向父节点 // 构造函数等... }这里有几个关键设计点世界坐标与网格坐标的映射worldPosition是根据节点索引(x, y)和预设的网格大小、原点计算出来的。这保证了算法在抽象的网格上运算但最终能输出具体的世界坐标供角色使用。移动惩罚movementPenalty这是实现差异化地形寻路的核心。在计算gCost时我们会加上这个惩罚值。比如普通平地的惩罚是0草地的惩罚是10沼泽地的惩罚是50。Astar算法在寻路时会自动倾向于选择总代价更低的路径从而让角色“聪明地”避开沼泽。节点状态分离isWalkable是静态的或由场景碰撞体决定而gCost、hCost、cameFromNode是每次寻路时的临时数据。每次开始新的寻路时都需要重置这些临时数据但无需重新创建节点对象提升性能。2.2 网格的生成与更新网格的初始化通常发生在游戏启动时或场景加载时。我们需要遍历整个寻路区域根据物理碰撞信息来设置每个节点的isWalkable状态。void CreateGrid() { grid new PathNode[gridSizeX, gridSizeY]; Vector3 worldBottomLeft transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2; for (int x 0; x gridSizeX; x) { for (int y 0; y gridSizeY; y) { // 计算该网格节点的世界中心点 Vector3 worldPoint worldBottomLeft Vector3.right * (x * nodeDiameter nodeRadius) Vector3.forward * (y * nodeDiameter nodeRadius); // 使用物理检测如BoxCast判断该点是否可通行 bool walkable !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask)); // 可以进一步根据worldPoint的y值或检测到的碰撞体标签设置不同的movementPenalty int penalty 0; if (Physics.Raycast(worldPoint Vector3.up * 5, Vector3.down, out RaycastHit hit, 10, terrainMask)) { if (hit.collider.CompareTag(Swamp)) penalty 50; else if (hit.collider.CompareTag(Road)) penalty -10; // 道路甚至可以提供奖励 } grid[x, y] new PathNode(walkable, worldPoint, x, y, penalty); } } }注意这里的CheckSphere或BoxCast的半径 (nodeRadius) 很关键。它应该略小于网格节点间距的一半以防止两个相邻的可通行节点之间因为检测区域重叠而被误判为不可通行。同时物理检测是比较耗性能的操作务必在初始化时完成避免在运行时每帧进行。对于动态障碍物如可破坏的墙、移动的箱子我们需要一套动态更新网格的机制。一个简单高效的方法是维护一个“障碍物-影响节点”的映射。当动态障碍物移动或状态改变时只更新它影响的局部网格节点而不是刷新整个网格。3. Astar算法核心实现详解有了网格我们就可以在上面运行Astar算法了。算法的核心是维护两个列表开放集合Open Set和关闭集合Closed Set。3.1 算法步骤拆解初始化将起点节点加入开放集合。设置其gCost 0hCost为到终点的启发式估计值。循环 a. 从开放集合中取出fCost最小如果fCost相同则取hCost最小的节点作为当前节点。 b. 将当前节点从开放集合移出加入关闭集合。 c. 如果当前节点就是终点说明路径已找到执行路径回溯。 d. 遍历当前节点的所有邻居节点通常是上下左右以及对角线共8个方向。 e. 对每个邻居节点 - 如果不可通行或在关闭集合中跳过。 - 计算从当前节点走到该邻居节点的新gCost当前节点的gCost 移动到邻居的成本 邻居的movementPenalty。 - 如果该邻居不在开放集合中或者新gCost小于它原有的gCost则更新这个邻居节点重置其gCost为新gCost重新计算hCost设置cameFromNode为当前节点。如果它原本不在开放集合则将其加入。路径回溯从终点节点开始沿着cameFromNode指针一路回溯到起点将经过的节点逆序存储就得到了从起点到终点的路径一系列世界坐标点。失败如果开放集合为空仍未到达终点说明没有可行路径。3.2 关键代码实现邻居查找与代价计算ListPathNode GetNeighbours(PathNode node) { ListPathNode neighbours new ListPathNode(); for (int x -1; x 1; x) { for (int y -1; y 1; y) { if (x 0 y 0) continue; // 跳过自身 int checkX node.x x; int checkY node.y y; // 检查是否在网格边界内 if (checkX 0 checkX gridSizeX checkY 0 checkY gridSizeY) { neighbours.Add(grid[checkX, checkY]); } } } return neighbours; }移动代价计算这是体现算法“智能”的地方。直线移动上下左右和斜线移动的成本通常不同。根据勾股定理斜线移动的距离是直线移动的√2倍约1.4倍。为了避免使用浮点数运算提高效率我们通常用整数近似。int GetDistance(PathNode nodeA, PathNode nodeB) { int dstX Mathf.Abs(nodeA.x - nodeB.x); int dstY Mathf.Abs(nodeA.y - nodeB.y); // 假设直线移动成本为10斜线移动成本为1410*1.4的近似 if (dstX dstY) { return 14 * dstY 10 * (dstX - dstY); } else { return 14 * dstX 10 * (dstY - dstX); } }在计算从当前节点到邻居的gCost增量时就使用这个GetDistance函数。同时启发式函数hCost也使用相同的计算方式这能保证算法在网格上的最优性。3.3 性能优化优先队列Heap的应用上述算法中每一步都需要从开放集合中找出fCost最小的节点。如果开放集合用普通的List存储每次查找都需要遍历整个列表时间复杂度是O(n)。当寻路区域很大时这会成为性能瓶颈。解决方案是使用**二叉堆Binary Heap**实现一个优先队列。它能保证每次取出最小元素和插入新元素的时间复杂度都是O(log n)极大提升了效率。public class HeapT where T : IHeapItemT { T[] items; int currentItemCount; // ... 插入(Insert)、移除第一个(RemoveFirst)、排序(SortUp/Down)等方法 } public interface IHeapItemT : IComparableT { int HeapIndex { get; set; } }让PathNode实现IHeapItemT接口基于fCost和hCost进行比较。然后将开放集合从ListPathNode替换为HeapPathNode。这是Astar实现中最重要的性能优化点之一务必在项目初期就引入。4. 从路径点到平滑移动让角色走得更自然算法输出的路径是一系列网格中心点的世界坐标。如果直接让角色按这个点序列移动会出现两个问题1. 路径是锯齿状的折线不自然2. 角色移动会严格经过每个点显得僵硬。4.1 路径平滑处理我们可以通过路径点简化和射线投射来获得更平滑的路径。路径点简化遍历路径点从起点开始向后的点发射射线。如果射线能直接打到更后面的点而不碰到障碍物说明中间的点可以省略。这能拉直路径。使用样条曲线对于简化后的关键路径点可以使用Catmull-Rom等样条曲线进行插值生成一条平滑的曲线路径。这能让角色的移动轨迹更加圆滑特别是在转弯处。public ListVector3 SimplifyPath(ListPathNode path) { ListVector3 waypoints new ListVector3(); Vector2 directionOld Vector2.zero; for (int i 1; i path.Count; i) { // 将节点方向转换为二维XZ平面 Vector2 directionNew new Vector2(path[i-1].x - path[i].x, path[i-1].y - path[i].y); if (directionNew ! directionOld) { // 方向改变添加前一个点为关键点 waypoints.Add(path[i-1].worldPosition); } directionOld directionNew; } waypoints.Add(path[path.Count-1].worldPosition); // 加入终点 return waypoints; }4.2 移动控制与动态避障有了平滑的路径点接下来就是控制角色移动。通常使用Vector3.MoveTowards或Vector3.SmoothDamp让角色朝向当前目标点移动。当角色接近一个目标点距离小于某个阈值时就将下一个路径点设为当前目标。但世界是动态的。寻路计算完成时路径是通的但角色移动过程中可能会有新的障碍物出现比如其他NPC走到了路径上。这就需要局部避障。方案一射线前瞻在角色移动方向前方持续发射射线检测即将碰撞的障碍物。一旦检测到可以触发一个轻微的转向力如使用向量场或简单的排斥力让角色绕开。这适合处理临时、小型的动态障碍。方案二定期重新寻路为每个移动角色设置一个“重新寻路计时器”。每隔零点几秒或者当角色偏离预定路径超过一定距离时就从角色的当前位置到最终目的地重新执行一次Astar寻路。这是最彻底的方法但比较耗费性能需要控制频率。方案三分层AI结合使用。长距离、全局性的路径规划用Astar短距离、紧急的避障用简单的物理射线或转向行为如Unity的NavMeshAgent的局部避障就是类似原理。这是最健壮的方案。5. 高级功能与扩展实践一个基础的Astar系统已经能解决大部分问题但要应对复杂场景还需要一些“进阶技能”。5.1 权重网格与区域划分我们之前提到了movementPenalty。我们可以将其扩展为一个完整的“权重网格”。例如在策略游戏中不同兵种对不同地形有不同偏好。骑兵在平原权重低在森林权重高步兵则相反。我们可以为每种单位类型预计算或运行时计算不同的权重网格然后在寻路时使用对应的网格实现真正的“智能”寻路。更进一步可以对网格进行区域划分Region。将连通的、属性相似的大片网格标记为同一个区域。在寻路时先进行粗粒度的区域间寻路找到需要经过的区域序列再在每个区域内部进行细粒度的网格寻路。这能极大减少需要搜索的节点数量适用于超大型地图。5.2 多单位协同与路径优化当一群单位需要移动到同一地点时如果每个单位都独立寻路不仅性能压力大还会导致单位挤在一起路径交叉混乱。群体移动Group Movement只为领队或第一个请求的单位计算一条完整路径。后续单位以这条路径为基础进行跟随。跟随者不需要完整的Astar寻路只需要计算如何跟上领队并加上一些分离、对齐的群体行为Boids算法简化版就能形成自然的队形。路径缓存与共享对于静态场景中固定的起点和终点比如游戏内固定的任务点之间可以将计算出的路径缓存起来。其他单位需要相同路径时直接读取缓存节省大量计算。流量场Flow Field对于大规模单位集群向同一目标移动如RTS游戏中上百个单位进攻Astar对每个单位寻路是不现实的。流量场技术预先为目标点计算整个网格上每个节点指向目标的最佳方向向量。移动时单位只需查询自己所在网格节点的方向向量然后朝那个方向移动即可。这本质上是Astar算法结果的另一种高效分发形式。5.3 与Unity生态的集成自研系统并不意味着要抛弃Unity的一切。恰恰相反我们应该善用引擎提供的工具。可视化调试在OnDrawGizmos中绘制网格可通行/不可通行用不同颜色、绘制计算出的路径、绘制当前开放集合和关闭集合的节点。这对于调试寻路逻辑至关重要能直观地看到算法是如何“思考”的。与NavMesh互补在超大型开放世界中可以混合使用。远距离移动用Astar在低精度大网格的世界地图上规划当接近目标区域时切换为Unity的NavMesh进行精细的、带动态避障的局部移动。这兼顾了效率和效果。使用Job System和Burst Compiler如果你的游戏需要同时进行大量寻路计算如大规模策略游戏可以考虑使用Unity的C# Job System将寻路算法并行化并用Burst Compiler编译成高性能的本地代码。这能将性能提升一个数量级但实现复杂度也更高。6. 实战避坑指南与性能调优纸上得来终觉浅绝知此事要躬行。下面是我在多个项目中踩过坑后总结出的经验。6.1 常见问题与排查角色卡住或抖动检查网格生成确保nodeRadius设置正确没有因检测盒重叠导致“孤岛”式不可通行节点。用Gizmos可视化网格仔细检查。检查路径点距离角色移动到目标点的判定距离阈值是否太小如果阈值小于每帧移动距离角色可能会在目标点附近来回振荡。通常阈值设为角色半径的0.5-0.8倍。检查动态障碍更新动态障碍物移除后其影响的网格节点isWalkable是否被正确更新如果没有路径依然认为那里不可通行。寻路速度慢网格粒度这是最大的影响因素。网格越小节点越多寻路越慢。在保证游戏性角色大小、障碍物精度的前提下尽量使用大网格。优化启发函数确保你的启发函数hCost不会高估实际代价否则可能找不到最优解但也尽量接近真实代价。网格环境下使用对角线距离前文的GetDistance就是很好的选择。使用Heap再次强调开放集合一定要用优先队列Heap不要用List。限制搜索范围对于超大型地图可以设置一个最大搜索节点数。超过这个数则认为路径过长或不存在提前终止避免卡死。路径看起来“很傻”比如贴着障碍物走或者绕远路检查移动惩罚movementPenalty是否设置合理如果惩罚值差异不够大算法可能不会明显偏好更优地形。检查对角移动规则在实现8方向邻居时要处理“穿墙”问题。如果当前节点的左侧和上侧都不可通行那么左上角的对角邻居节点实际上也是不可直接到达的因为会卡在墙角。需要在获取邻居时增加额外的射线检测来判断对角移动是否合法。6.2 性能分析与监控在Unity Profiler的CPU使用率中观察你的寻路函数调用。如果单次寻路耗时超过几毫秒比如在移动设备上就需要优化了。分帧寻路如果一帧内触发多次寻路可以将它们分散到多帧中执行避免单帧卡顿。使用协程Coroutine或自己维护一个寻路请求队列每帧只处理一个或几个。LOD寻路对于距离玩家很远的NPC可以使用更粗糙的网格低精度进行寻路只有玩家附近的NPC才使用精细网格。这需要维护多套不同精度的网格数据。打造一个健壮、高效的3D Astar寻路系统是一个从理解原理、实现基础、不断调试到深度优化的完整过程。它不像直接调用NavMeshAgent.SetDestination()那么简单但带来的灵活性和控制力是无可比拟的。当你看到自己编写的代码驱动着成千上万的单位在复杂的地形中井然有序地行进时那种成就感正是游戏开发的乐趣所在。这套系统将成为你技术工具箱里一件强大而趁手的武器让你有能力去实现那些天马行空的游戏创意。

相关新闻

CTF实战:从Pyc反编译到RSA密码破解全流程解析

CTF实战:从Pyc反编译到RSA密码破解全流程解析

1. 项目概述与核心思路拆解 最近在复盘一场数据安全大赛的题目,其中一道融合了逆向工程和密码学的综合题让我印象挺深。题目给了一个Python编译后的 .pyc 文件,要求我们从中找到线索,最终解密一段用RSA算法加密的Flag。这种“逆向分析密码…

2026/7/29 3:37:42 阅读更多 →
PEMFC建模与Simulink实现:从静态到动态的燃料电池仿真

PEMFC建模与Simulink实现:从静态到动态的燃料电池仿真

1. 质子交换膜燃料电池(PEMFC)建模基础燃料电池作为清洁能源技术的重要代表,在汽车动力系统、分布式发电等领域展现出巨大潜力。其中质子交换膜燃料电池(PEMFC)因其启动快速、功率密度高、工作温度低等优势,成为当前最受关注的技术路线。要深入理解PEMFC…

2026/7/29 3:37:42 阅读更多 →
蚂蚁S9矿板PS并发和竞争驱动 ---目录

蚂蚁S9矿板PS并发和竞争驱动 ---目录

参考 蚂蚁S9矿板引脚定义.csdn 蚂蚁S9矿板PS并发和竞争驱动 —目录.csdn 蚂蚁S9矿板PS并发和竞争驱动 —原子操作.csdn 蚂蚁S9矿板PS并发和竞争驱动 —自旋锁.csdn 蚂蚁S9矿板PS并发和竞争驱动 —信号量.csdn 蚂蚁S9矿板PS并发和竞争驱动 —互斥体.csdn 设备树 #include <…

2026/7/29 3:37:42 阅读更多 →

最新新闻

如何在广州做小程序搭建?本地平台和线上平台差在哪?

如何在广州做小程序搭建?本地平台和线上平台差在哪?

在广州做小程序搭建&#xff0c;容易选错的地方是把“本地公司”和“线上平台”当成两种固定质量等级。本地团队不一定都擅长复杂开发&#xff0c;线上平台也不一定只能提供通用模板&#xff0c;真正差别在服务方式、产品边界和后续协作成本。企业应该先判断小程序是标准经营工…

2026/7/29 6:21:42 阅读更多 →
深入解析多边形填充算法:从扫描线到GPU光栅化的核心原理与实现

深入解析多边形填充算法:从扫描线到GPU光栅化的核心原理与实现

1. 项目概述&#xff1a;从像素到画面的魔法在屏幕上看到一个色彩斑斓的3D游戏角色&#xff0c;或是一幅由矢量图形软件绘制的复杂插画时&#xff0c;你是否想过&#xff0c;这些平滑的曲面和丰富的色彩是如何由计算机“画”出来的&#xff1f;答案的核心之一&#xff0c;就是多…

2026/7/29 6:21:42 阅读更多 →
C/C++动态内存管理:从原理到实战,掌握面试核心与工程实践

C/C++动态内存管理:从原理到实战,掌握面试核心与工程实践

1. 项目概述&#xff1a;为什么动态内存管理是C/C面试的“必答题”&#xff1f;最近在帮团队面试一些C/C方向的候选人&#xff0c;发现一个挺有意思的现象&#xff1a;无论面试官是问基础语法还是项目经验&#xff0c;最后总会绕回到动态内存管理这个话题上。候选人要么对mallo…

2026/7/29 6:21:42 阅读更多 →
Uniapp微信小程序分享功能全链路实践:从API调用到数据追踪

Uniapp微信小程序分享功能全链路实践:从API调用到数据追踪

1. 项目概述&#xff1a;为什么小程序分享功能值得深挖最近在做一个基于uniapp的微信小程序项目&#xff0c;产品经理提了一个看似简单的需求&#xff1a;在商品详情页和活动页增加分享功能。我一开始觉得这还不简单&#xff0c;不就是调用一下微信的API吗&#xff1f;但真正上…

2026/7/29 6:21:42 阅读更多 →
用Scratch编程可视化鸽巢原理:从数学公理到交互式模拟实验

用Scratch编程可视化鸽巢原理:从数学公理到交互式模拟实验

1. 从“鸽巢”到“抽屉”&#xff1a;一个数学原理的趣味化呈现如果你是一位数学老师&#xff0c;或者是一位想给孩子做数学启蒙的家长&#xff0c;你肯定遇到过这样的难题&#xff1a;如何把一个听起来有点抽象、甚至有点枯燥的数学原理&#xff0c;讲得让孩子眼睛发亮&#x…

2026/7/29 6:21:42 阅读更多 →
盘锦啤酒厂团购规则怎么问?亲测沟通流程清楚吗

盘锦啤酒厂团购规则怎么问?亲测沟通流程清楚吗

平时朋友小聚、单位餐桌、家里请客&#xff0c;买啤酒最怕什么&#xff1f;不是单纯怕贵&#xff0c;而是怕“问的时候说不清、拿到手不明白”&#xff1a;到底是不是鲜啤&#xff1f;生产日期是哪天&#xff1f;几箱起算团购&#xff1f;口味能不能混搭&#xff1f;冷藏怎么放…

2026/7/29 6:20:42 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02&#xff1a;合并知识功能&#xff0c;给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中&#xff0c;我们学习了如何构建一个基础的 AI 问答系统&#xff0c;通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景&#xff1a;…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行&#xff1a;AI Agent的范式转变过去两年&#xff0c;大语言模型最显著的应用形态是聊天机器人——用户提问&#xff0c;AI回答。但真正的生产力革命发生在2023年下半年&#xff1a;当AI学会主动调用工具完成任务时&#xff0c;生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档&#xff0c;可以直接使用&#xff01;系统支持图片、视频、摄像头等多种方式检测裂缝&#xff0c;功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像&#xff01; pubg绝地求生目标检测数据集 1分类&#xff1a;e_body&#xff0c;14905个标签&#xff0c;txt格式 共计14244张图&#xff0c;99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别&#xff1a; allies enemy tag图片总量&#xff1a;7247张训练集&#xff1a;5139张验证集&#xff1a;1425张测试集&#xff1a;683张标注状态&#xff1a;全部已标注&#xff0c;即拿即用数据格式&#xff1a;支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻