Unity网格合并优化:保持层级结构降低Draw Call的实战方案
1. 项目概述为什么我们需要批量合并建筑网格在Unity中制作大型场景尤其是城市、城堡或复杂的室内环境时最头疼的问题之一就是Draw Call。每一个独立的网格、每一种不同的材质都会向GPU发送一次绘制指令。当你的场景里塞满了成百上千个由基础立方体、圆柱体拼成的建筑模块时性能瓶颈立刻就出现了。游戏帧率下降、编辑器卡顿这些都是Draw Call爆炸的典型症状。CombineMeshes或者说网格合并技术就是解决这个问题的核心手段。它的原理并不复杂将多个使用相同材质的静态网格在运行时或烘焙时合并成一个大的网格。这样一来原本需要几十次甚至上百次Draw Call来渲染的建筑群可能只需要几次。这对于移动端、WebGL等性能受限的平台来说是至关重要的优化步骤。但很多开发者尤其是刚接触场景优化的朋友会直接使用Unity自带的StaticBatching静态批处理或者简单地写个脚本遍历子物体调用Mesh.CombineMeshes。这样做往往会导致一个严重的问题合并后的物体其层级结构Hierarchy完全被打乱所有子物体都消失了只剩下一个合并后的大网格物体。这对于后续的场景管理、动态交互比如只想破坏建筑的一部分、LOD多层次细节设置来说简直是灾难。因此这个项目的核心目标非常明确实现建筑模块的批量网格合并同时完美保持它们在Hierarchy中的原始层级结构。这不仅仅是优化更是为了优化之后不牺牲项目的可维护性和扩展性。下面我将从一个实战者的角度拆解其中的技术细节、实操步骤以及那些官方文档里不会告诉你的“坑”。2. 核心思路与方案选型手动合并 vs. 运行时合并在动手写代码之前我们必须明确两种主要的合并策略及其适用场景这决定了我们整个方案的架构。2.1 静态合并编辑器工具这是最常用、也是效果最好的方式。我们编写一个编辑器扩展Editor Tool在场景编辑阶段由开发者手动或半自动地触发合并操作。合并后的新网格和材质会作为资源Asset保存到项目中并生成一个使用该资源的新GameObject来替换原有的复杂结构。优点零运行时开销合并操作只在编辑时执行一次游戏运行时直接加载最终的低Draw Call模型没有任何合并计算消耗。结果完全可控可以仔细检查合并后的模型、UV、材质是否正确并进行手动调整。便于资源管理生成的预制体Prefab可以像普通模型一样进行版本管理、AB打包。缺点失去模块化编辑能力合并后原始的方块单元无法再在场景中直接移动、旋转。如果需要修改必须回退到未合并的状态修改后再重新合并。增加资源体积生成了新的网格和材质文件。适用场景对于确定不会在运行时改变形态的静态建筑、地形装饰、固定场景道具这是首选方案。我们的教程也将以此为重点。2.2 运行时动态合并通过脚本在游戏启动时如Awake或Start中动态查找并合并网格。StaticBatching本质上也是Unity在运行时帮你做的一种自动合并。优点保持编辑灵活性在编辑器中你依然可以自由摆放各个模块。适合程序化生成内容对于运行时由代码生成的建筑可以在生成后立即合并。缺点增加启动时间或帧时间开销合并计算本身需要CPU时间对于大量网格可能引起卡顿。内存管理更复杂需要妥善处理合并前后网格的内存分配与释放避免泄露。对动态物体无效如果合并后的物体或其父物体有任何移动、旋转、缩放非批处理静态标识批处理会失效。适用场景适合中小型、模块化程度高、且可能在运行时通过配置切换组合的场景。或者用于合并程序化生成且之后不再移动的物体。注意保持层级的关键在于我们不是粗暴地合并整个根节点下的所有东西。而是有选择地、分组合并。例如一栋房子我们可能将“墙体”下的所有方块合并成一个网格将“屋顶”下的所有瓦片合并成另一个网格而“门窗”可能因为材质不同或需要独立交互而不合并。这样在Hierarchy中“墙体”、“屋顶”、“门窗”这些父节点和其组织结构依然存在只是它们的子节点原来的无数个Cube被替换成了合并后的单个网格物体。3. 工具选型与准备工作工欲善其事必先利其器。除了Unity自带的功能选择合适的工具能让我们的工作流更顺畅。3.1 必需组件与知识准备MeshFilter 和 MeshRenderer这是网格合并操作直接打交道的两个核心组件。MeshFilter存储网格数据MeshRenderer负责渲染并持有材质。材质与材质球合并的基本单位是共享同一材质的网格。确保你想要合并的建筑模块使用的是同一个材质球Material而不是多个材质实例。如果颜色不同应该使用材质属性如_Color或顶点颜色来区分而不是创建新材质。编辑器脚本基础我们需要创建Editor文件夹下的C#脚本并使用UnityEditor命名空间中的类如EditorWindow,Editor,Selection等。预制体工作流强烈建议将你的建筑模块如各种形状的墙壁、地板、屋顶预制体规范化管理。合并操作的目标通常是这些预制体在场景中的实例。3.2 可选辅助工具Obi Advanced Mesh Combiner / Mesh Baker这些是Asset Store上非常强大的第三方网格合并插件。它们提供了图形化界面、更完善的合并选项如处理光照贴图UV、LOD合并等。如果你的项目预算允许且合并需求非常复杂使用这些成熟工具可以节省大量时间。但本教程旨在理解原理并实现核心功能因此我们将从零开始构建。ProBuilder / SabreCSG如果你是在Unity内部直接进行场景建模这些工具创建的面片通常已经过优化但将其转换为常规网格后同样面临合并需求。4. 分步实现编写保持层级的网格合并编辑器工具接下来是核心实操部分。我们将创建一个名为HierarchyPreservingMeshCombiner的编辑器工具。4.1 创建编辑器窗口首先在项目的Editor文件夹下创建一个C#脚本。using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.Linq; // 用于便捷的集合操作 public class HierarchyPreservingMeshCombiner : EditorWindow { // 窗口实例获取方法 [MenuItem(Tools/场景优化/层级保持网格合并器)] static void Init() { var window GetWindowHierarchyPreservingMeshCombiner(); window.titleContent new GUIContent(网格合并器); window.Show(); } // 工具界面变量 private GameObject targetRoot; // 要合并的根物体 private string combinedMeshName Combined_Mesh; private bool combineInactive false; private bool createPrefab true; private string savePath Assets/CombinedMeshes/; // 绘制编辑器窗口界面 void OnGUI() { GUILayout.Label(层级保持网格合并设置, EditorStyles.boldLabel); targetRoot (GameObject)EditorGUILayout.ObjectField(目标根物体, targetRoot, typeof(GameObject), true); combinedMeshName EditorGUILayout.TextField(合并网格名称, combinedMeshName); combineInactive EditorGUILayout.Toggle(包含未激活物体, combineInactive); createPrefab EditorGUILayout.Toggle(生成预制体, createPrefab); savePath EditorGUILayout.TextField(保存路径, savePath); EditorGUILayout.Space(); if (GUILayout.Button(开始合并选中物体及其子物体)) { if (targetRoot null) { EditorUtility.DisplayDialog(错误, 请先指定目标根物体, 确定); return; } CombineMeshesUnderRoot(targetRoot); } if (GUILayout.Button(合并场景中所有选中物体)) { if (Selection.gameObjects.Length 0) { EditorUtility.DisplayDialog(错误, 请在场景中选中至少一个物体, 确定); return; } // 这里可以扩展为遍历多个选中的根物体 CombineMeshesUnderRoot(Selection.activeGameObject); } } }这段代码创建了一个简单的编辑器窗口包含一些基本设置选项。核心逻辑在CombineMeshesUnderRoot方法中。4.2 实现核心合并逻辑保持层级这是整个工具的灵魂。思路是递归遍历目标根节点下的所有子物体但以直接使用相同材质的叶子节点为分组依据进行合并。private void CombineMeshesUnderRoot(GameObject root) { if (root null) return; // 1. 收集所有需要处理的MeshRenderer ListMeshRenderer allRenderers new ListMeshRenderer(); CollectRenderers(root.transform, allRenderers); if (allRenderers.Count 0) { Debug.LogWarning($在 {root.name} 下未找到任何MeshRenderer。); return; } // 2. 按材质进行分组 DictionaryMaterial, ListMeshRenderer materialToRenderers new DictionaryMaterial, ListMeshRenderer(); foreach (var renderer in allRenderers) { // 跳过没有材质或MeshFilter的渲染器 if (renderer.sharedMaterials.Length 0 || renderer.GetComponentMeshFilter() null) continue; // 注意一个MeshRenderer可能有多个子网格SubMesh对应多个材质。 // 这里简化处理只取第一个材质作为分组键。对于复杂模型需要循环所有材质。 Material keyMat renderer.sharedMaterial; if (keyMat null) continue; if (!materialToRenderers.ContainsKey(keyMat)) { materialToRenderers[keyMat] new ListMeshRenderer(); } materialToRenderers[keyMat].Add(renderer); } // 3. 为每个材质组创建合并后的父物体 DictionaryMaterial, GameObject combinedParents new DictionaryMaterial, GameObject(); foreach (var kvp in materialToRenderers) { Material mat kvp.Key; ListMeshRenderer renderers kvp.Value; if (renderers.Count 2) { // 如果只有一个渲染器合并意义不大跳过或直接保留原物体 Debug.Log($材质 {mat.name} 对应的渲染器少于2个跳过合并。); continue; } // 创建新的父物体命名并放置在root下 string parentName ${combinedMeshName}_{mat.name}; GameObject newParent new GameObject(parentName); newParent.transform.SetParent(root.transform, false); // 保持与世界坐标一致 combinedParents[mat] newParent; // 4. 准备CombineInstance数组 ListCombineInstance combineInstances new ListCombineInstance(); ListTransform transformsToDeactivate new ListTransform(); foreach (var renderer in renderers) { MeshFilter mf renderer.GetComponentMeshFilter(); if (mf null || mf.sharedMesh null) continue; // 创建CombineInstance CombineInstance ci new CombineInstance(); ci.mesh mf.sharedMesh; ci.transform renderer.transform.localToWorldMatrix; // 关键转换矩阵 combineInstances.Add(ci); // 记录原物体后续禁用 transformsToDeactivate.Add(renderer.transform); } // 5. 执行合并 Mesh combinedMesh new Mesh(); combinedMesh.name parentName; // 对于大量网格可能需要使用indexFormat为32位 combinedMesh.indexFormat UnityEngine.Rendering.IndexFormat.UInt32; combinedMesh.CombineMeshes(combineInstances.ToArray(), true); // 第二个参数为true表示合并子网格 // 6. 为合并后的父物体添加组件 MeshFilter newMF newParent.AddComponentMeshFilter(); newMF.sharedMesh combinedMesh; MeshRenderer newMR newParent.AddComponentMeshRenderer(); newMR.sharedMaterial mat; // 使用分组材质 // 7. 禁用原始渲染物体可选也可以直接Destroy foreach (var trans in transformsToDeactivate) { trans.gameObject.SetActive(false); // 如果你确定不再需要可以DestroyImmediate(trans.gameObject); // 但建议先禁用检查合并结果无误后再手动清理。 } // 8. 保存网格资源到项目 SaveMeshAsset(combinedMesh, parentName); } Debug.Log($合并完成在 {root.name} 下生成了 {combinedParents.Count} 个合并物体。); // 可选选中所有新生成的合并物体 Selection.objects combinedParents.Values.Select(go (Object)go).ToArray(); } // 递归收集渲染器 private void CollectRenderers(Transform root, ListMeshRenderer outputList) { if (!combineInactive !root.gameObject.activeInHierarchy) return; MeshRenderer mr root.GetComponentMeshRenderer(); if (mr ! null) { outputList.Add(mr); } foreach (Transform child in root) { CollectRenderers(child, outputList); } } // 保存Mesh为Asset文件 private void SaveMeshAsset(Mesh mesh, string name) { if (!System.IO.Directory.Exists(savePath)) { System.IO.Directory.CreateDirectory(savePath); } string assetPath System.IO.Path.Combine(savePath, ${name}.asset); // 防止覆盖已有文件 assetPath AssetDatabase.GenerateUniqueAssetPath(assetPath); AssetDatabase.CreateAsset(mesh, assetPath); AssetDatabase.SaveAssets(); Debug.Log($网格已保存: {assetPath}); }4.3 关键参数与原理详解CombineInstance.transform这是保持模型位置、旋转、缩放正确的核心。每个子网格在合并时都需要提供其从本地坐标系到世界坐标系的变换矩阵localToWorldMatrix。这样合并后的大网格才能正确还原所有小模块在世界中的位置。Mesh.CombineMeshes(combineInstances, mergeSubMeshes)mergeSubMeshes参数设为true时会将所有输入的网格合并成一个子网格SubMesh这意味着最终只能使用一个材质。这正是我们按材质分组后合并的目的。如果设为false则每个输入网格会保留为自己的子网格合并后的MeshRenderer需要使用一个材质数组。这适用于合并多个不同材质但想保持在一个Draw Call内的情况需要支持多子网格的Shader。禁用 vs. 销毁原始物体代码中选择了SetActive(false)。这是一个安全的选择让你有机会检查合并结果。确认无误后可以运行一个清理脚本或手动删除这些被禁用的物体。直接DestroyImmediate在编辑器脚本中虽然可以但一旦出错无法撤销。网格索引格式 (indexFormat):当合并的网格顶点数可能超过6553516位索引的最大值时必须将indexFormat设置为UInt32否则会导致渲染错误或崩溃。5. 高级议题与常见问题排查即使核心流程走通在实际项目中你还会遇到各种边界情况和难题。5.1 光照贴图UV的处理如果你的场景使用了烘焙光照Lightmapping那么合并网格后新的网格将没有光照贴图UV。这会导致烘焙的光照信息无法正确应用。解决方案合并前生成UV2在合并前确保每个原始网格已经生成了第二套UVUV2用于光照贴图。可以在导入设置中勾选“Generate Lightmap UVs”或使用代码Mesh.GenerateSecondaryUVSet()。合并后重新烘焙网格合并完成后你需要将新的合并物体标记为Static包含Lightmap Static然后在Lighting窗口中重新烘焙光照。因为网格的几何信息已经完全改变旧的光照贴图数据不再适用。5.2 碰撞体与导航网格的同步合并操作只处理了MeshFilter和MeshRenderer。如果你的原始建筑模块带有MeshCollider合并后它们会随着原物体被禁用而失效。解决方案为合并物体添加MeshCollider在创建合并父物体后可以为其添加一个MeshCollider并赋予合并后的网格。但要注意一个复杂的大网格碰撞体性能可能很差。使用简化碰撞体或复合碰撞体更优的做法是不为合并后的视觉模型添加碰撞体而是专门创建一个简化的碰撞体层级比如用一些BoxCollider或凸包MeshCollider来近似整个建筑的体积。导航网格NavMesh也是基于场景中的碰撞体或特定标记来烘焙的因此需要同步更新。5.3 材质球实例化问题代码中我们使用renderer.sharedMaterial进行分组。这要求所有要合并的物体必须引用同一个材质球资产。如果它们在编辑器中通过修改材质属性产生了多个材质实例即使看起来一样sharedMaterial也会指向不同的实例导致无法合并。排查与解决在Project视图中搜索“(Instance)”来查找材质实例。编写预处理脚本将相同参数的材质实例合并回同一个材质球。在设计模块化资产时就规定使用材质属性如通过脚本设置MaterialPropertyBlock来改变颜色等而非创建新实例。5.4 合并后模型接缝或光照断裂有时合并后在原本模块衔接的地方会出现细微的缝隙或光照不连续。原因与解决顶点位置不精确确保你的基础模块如Cube在建模时顶点坐标是精确对齐的没有微小的浮点误差。在Unity中检查Transform的Position值是否为整数或规整的小数。法线问题合并时顶点法线是直接取自原网格。在模块边缘两个相邻面的法线方向是硬边。如果希望得到平滑的外观需要在合并前或合并后对内部接缝处的顶点法线进行平滑处理但这通常不是建筑模块的需求建筑需要硬朗的边角。光照贴图接缝这是重新烘焙光照后最常见的问题。需要在UV2展开时确保有足够的padding并在Unity的Model Import设置或第三方建模软件中处理好UV岛之间的间距。6. 实操心得与性能考量经过多个项目的实践我总结出以下几点心得合并的粒度是关键。不要试图将整个场景合并成一个网格。应根据视觉区块、材质和功能来划分。例如将一栋建筑的外墙合并内部家具合并植物合并成另一组。这样即使在合并后你仍然可以通过禁用/启用整个合并体来控制大范围的显示/隐藏。善用预制体变体。将合并后的结果保存为预制体。你可以创建多个变体比如“建筑_合并版”和“建筑_未合并版”分别用于发布版本和开发阶段编辑。在性能与内存间权衡。合并减少了Draw Call但增加了单个网格的复杂度顶点和三角形数。对于GPU处理一个包含10万个三角形的大网格和处理100个各1000个三角形的小网格前者通常更高效。但极端情况下一个过于巨大的网格可能超出某些低端设备的处理能力。同时合并后的网格无法享受视锥体剔除Frustum Culling对单个小物体的优化。如果一栋大楼只有一角在屏幕内整个大楼的网格都需要被提交给GPU。因此合理的分组合并尤为重要。自动化与手动检查结合。可以编写更智能的工具自动按材质、按层级深度、按空间位置进行分组合并。但在关键场景合并后一定要手动检查模型、光照和碰撞。自动化是提高效率的手段但最终质量需要人工把关。版本控制注意事项。合并生成的.mesh和.mat文件是二进制资源在版本控制如Git下的差异对比和合并比较困难。确保团队有清晰的规范知道这些资源是如何生成的并且在需要修改时是回退到原始模块重新合并还是直接编辑合并后的资源。最后记住网格合并是优化手段不是目的。它的目标是提升运行时性能。在着手合并之前先用Unity的Profiler和Frame Debugger工具分析一下确认Draw Call确实是当前场景的性能瓶颈。有时候通过合理的材质合批Texture Atlas、简化模型面数、使用GPU Instancing等技术可能以更小的代价获得可观的性能提升。将层级保持网格合并作为你场景优化工具箱中的一件利器在正确的时机使用它才能打造出既流畅又易于维护的高质量项目。

相关新闻

如何用League Akari成为英雄联盟高手:免费终极助手完全指南

如何用League Akari成为英雄联盟高手:免费终极助手完全指南

如何用League Akari成为英雄联盟高手:免费终极助手完全指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是一款基于…

2026/7/31 12:53:22 阅读更多 →
SPT-AKI Profile Editor:3分钟掌握离线版塔科夫存档编辑器的终极使用技巧

SPT-AKI Profile Editor:3分钟掌握离线版塔科夫存档编辑器的终极使用技巧

SPT-AKI Profile Editor:3分钟掌握离线版塔科夫存档编辑器的终极使用技巧 【免费下载链接】SPT-AKI-Profile-Editor Программа для редактирования профиля игрока на сервере SPT-AKI 项目地址: https://gitcod…

2026/7/31 12:53:22 阅读更多 →
深入解析:15MW海上风机开源模型的7大核心技术实现

深入解析:15MW海上风机开源模型的7大核心技术实现

深入解析:15MW海上风机开源模型的7大核心技术实现 【免费下载链接】IEA-15-240-RWT 15MW reference wind turbine repository developed in conjunction with IEA Wind 项目地址: https://gitcode.com/gh_mirrors/ie/IEA-15-240-RWT IEA-15-240-RWT作为国际能…

2026/7/31 12:53:22 阅读更多 →

最新新闻

Python基础操作在医药数据处理中的实战应用与避坑指南

Python基础操作在医药数据处理中的实战应用与避坑指南

1. 项目概述:当医药数据处理遇上Python基础操作最近在整理资料时,翻到了这本《Python程序设计实验教程——以医药数据处理为例》的第七章。这一章的标题是“简单操作题”,但如果你真以为它只是“简单”地敲几行代码,那可能就错过了…

2026/7/31 13:31:35 阅读更多 →
Windows下Python-docx安装指南:从环境配置到实战应用

Windows下Python-docx安装指南:从环境配置到实战应用

1. 项目概述:为什么我们需要Python-docx? 如果你在Windows上搞Python开发,尤其是需要处理Word文档,那你大概率绕不开 python-docx 这个库。它不是什么新潮玩意儿,但绝对是办公自动化和数据处理领域里的“瑞士军刀”…

2026/7/31 13:31:35 阅读更多 →
小程序Canvas签名图片翻转问题:从原理到解决方案

小程序Canvas签名图片翻转问题:从原理到解决方案

1. 从需求到实现:为什么小程序里的签名需要“翻转”? 最近在做一个涉及用户在线签署确认单的微信小程序项目,用的是uni-app框架。功能本身不复杂:用户在一块画布上签名,然后生成图片保存或上传。但就在我以为快要收工时…

2026/7/31 13:31:35 阅读更多 →
30KG协作机器人解析:柔性力控与恒力打磨,越疆凭智能架构领行业

30KG协作机器人解析:柔性力控与恒力打磨,越疆凭智能架构领行业

2026年,国产重载协作机器人的产业竞争已经完成结构性迭代。此前行业比拼的核心是负载参数、机身刚性与量产价格,聚焦解决30KG物料码垛、重载上下料的基础自动化问题。但随着柔性制造全面落地,制造业对重载设备的需求不再局限于“搬得动、码得…

2026/7/31 13:31:35 阅读更多 →
Linux 磁盘分区详解:EFI、/boot、swap、/ 与 /data 到底怎么分?

Linux 磁盘分区详解:EFI、/boot、swap、/ 与 /data 到底怎么分?

前言 第一次手动安装 Linux 时,很多人都会停在“安装目标位置”或“手动分区”界面,不知道这些挂载点到底应该怎么选: /boot/efi /boot swap / /home /data 它们看起来都像“分区”,但实际上混合了几种不同概念: /b…

2026/7/31 13:31:35 阅读更多 →
Oracle:使用Java存储过程或函数来扩展数据库的功能

Oracle:使用Java存储过程或函数来扩展数据库的功能

在Oracle数据库中,可以使用Java存储过程或函数来扩展数据库的功能。Oracle数据库提供了JDBC (Java Database Connectivity) 支持,这使得Java代码可以直接嵌入到PL/SQL代码中。下面是如何在Oracle数据库中编写一个Java函数的步骤。步骤 1: 确保Java环境已…

2026/7/31 13:30:35 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/7/31 4:19:39 阅读更多 →

月新闻