using System.Collections.Generic; using UnityEngine; /// /// 网格合并工具类 /// public static class MeshCombineUtils { /// /// 收集渲染器 /// public static List CollectRenderers(List roots) { List allRenderers = new(); foreach (var root in roots) { if (!root) { continue; } var render = root.GetComponentsInChildren(); if (render is not { Length: > 0 }) { continue; } allRenderers.AddRange(render); } return allRenderers; } /// /// 根据相互距离对渲染器进行分组 /// 只要物体与组内任意一个物体距离小于 maxDistance,就将其加入该组 /// public static Dictionary> GroupRenderersByProximity(List renderers, float maxDistance) { var groups = new Dictionary>(); var groupIndex = 0; // 已分组的渲染器 var processedRenderers = new HashSet(); // 对所有渲染器进行处理 while (processedRenderers.Count < renderers.Count) { // 找到第一个未处理的渲染器作为新组的起点 Renderer startRenderer = FindFirstUnprocessedRenderer(renderers, processedRenderers); if (startRenderer == null) break; // 创建新组并添加起点渲染器 var currentGroup = new List { startRenderer }; processedRenderers.Add(startRenderer); // 扩展当前组 ExpandGroupByProximity(renderers, currentGroup, processedRenderers, maxDistance); // 添加组到结果 groups.Add($"Group_{groupIndex}", currentGroup); groupIndex++; } Debug.Log($"基于邻近距离分组:将{renderers.Count}个渲染器分成{groups.Count}个组,最大距离为{maxDistance}"); return groups; } /// /// 查找第一个未处理的渲染器 /// private static Renderer FindFirstUnprocessedRenderer(List renderers, HashSet processedRenderers) { foreach (var renderer in renderers) { if (!processedRenderers.Contains(renderer)) { return renderer; } } return null; } /// /// 通过邻近距离扩展组 /// private static void ExpandGroupByProximity(List allRenderers, List currentGroup, HashSet processedRenderers, float maxDistance) { bool addedNew = true; while (addedNew) { addedNew = false; // 查找与当前组中任意一个渲染器距离在阈值内的未处理渲染器 foreach (var renderer in allRenderers) { if (processedRenderers.Contains(renderer)) continue; // 检查是否与组内任何一个渲染器距离小于阈值 if (IsCloseToAnyInGroup(renderer, currentGroup, maxDistance)) { currentGroup.Add(renderer); processedRenderers.Add(renderer); addedNew = true; } } } } /// /// 检查渲染器是否与组内任一渲染器距离小于阈值 /// private static bool IsCloseToAnyInGroup(Renderer renderer, List group, float maxDistance) { foreach (var groupRenderer in group) { float distance = CalculateDistance(renderer, groupRenderer); if (distance <= maxDistance) { return true; } } return false; } /// /// 计算两个渲染器之间的距离 /// private static float CalculateDistance(Renderer renderer1, Renderer renderer2) { return Vector3.Distance(renderer1.transform.position, renderer2.transform.position); } /// /// 计算渲染组的中心点 /// public static Vector3 CalculateGroupCenter(List group) { if (group.Count == 0) return Vector3.zero; var sum = Vector3.zero; foreach (var renderer in group) { sum += renderer.transform.position; } return sum / group.Count; } /// /// 根据圆形区域对渲染器进行分组(原始算法,保留作参考) /// public static Dictionary> GroupRenderersByCircularDistance(List renderers, float maxDistance) { var groups = new Dictionary>(); var groupIndex = 0; // 已分组的渲染器 var processedRenderers = new HashSet(); // 对所有渲染器进行处理 while (processedRenderers.Count < renderers.Count) { // 找到第一个未处理的渲染器作为新组的起点 Renderer startRenderer = FindFirstUnprocessedRenderer(renderers, processedRenderers); if (startRenderer == null) break; // 创建新组 var currentGroup = new List(); currentGroup.Add(startRenderer); processedRenderers.Add(startRenderer); bool addedNew = true; while (addedNew) { addedNew = false; // 计算当前组的中心点 var groupCenter = CalculateGroupCenter(currentGroup); // 查找距离中心点在阈值内的未处理渲染器 foreach (var renderer in renderers) { if (processedRenderers.Contains(renderer)) continue; var distance = Vector3.Distance(groupCenter, renderer.transform.position); if (!(distance <= maxDistance)) continue; currentGroup.Add(renderer); processedRenderers.Add(renderer); addedNew = true; } } groups.Add($"Group_{groupIndex}", currentGroup); groupIndex++; } Debug.Log($"基于圆形区域分组:将{renderers.Count}个渲染器分成{groups.Count}个组,半径为{maxDistance}"); return groups; } }