Files
test/Assets/ModelRenderer/Scripts/Editor/RemoveInvalidMeshFromFolder.cs
T
2026-02-15 21:34:38 +07:00

166 lines
4.9 KiB
C#

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class RemoveInvalidMeshFromFolder
{
private const float MinBoundsSize = 0.2f;
[MenuItem("Tools/Cleanup/Remove Invalid Meshes (Select Folder)")]
static void RemoveInvalidMeshesFromFolder()
{
string absFolder = EditorUtility.OpenFolderPanel(
"Select folder to clean prefabs (remove invalid MeshColliders)",
Application.dataPath,
""
);
if (string.IsNullOrEmpty(absFolder))
return;
if (!absFolder.StartsWith(Application.dataPath))
{
EditorUtility.DisplayDialog("Invalid Folder",
"Please select a folder inside your project's Assets folder.",
"OK");
return;
}
string relFolder = "Assets" + absFolder.Substring(Application.dataPath.Length);
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { relFolder });
if (prefabGuids == null || prefabGuids.Length == 0)
{
EditorUtility.DisplayDialog("No Prefabs Found",
$"No prefabs found in the selected folder:\n{relFolder}",
"OK");
return;
}
int scanned = 0;
int modified = 0;
List<string> errors = new List<string>();
try
{
AssetDatabase.StartAssetEditing();
foreach (string guid in prefabGuids)
{
if (string.IsNullOrEmpty(guid))
continue;
string path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path))
continue;
scanned++;
GameObject instance = null;
try
{
instance = PrefabUtility.LoadPrefabContents(path);
}
catch (System.Exception ex)
{
errors.Add($"{path}: Failed to load - {ex.Message}");
continue;
}
if (instance == null)
{
errors.Add($"{path}: LoadPrefabContents returned null");
continue;
}
bool changed = false;
MeshCollider[] meshColliders = instance.GetComponentsInChildren<MeshCollider>(true);
if (meshColliders != null)
{
List<MeshCollider> toRemove = new List<MeshCollider>();
foreach (MeshCollider mc in meshColliders)
{
if (mc == null)
continue;
if (ShouldRemoveMeshCollider(mc, out string reason))
{
toRemove.Add(mc);
}
}
foreach (MeshCollider mc in toRemove)
{
if (mc != null)
{
Object.DestroyImmediate(mc);
changed = true;
}
}
}
if (changed)
{
try
{
PrefabUtility.SaveAsPrefabAsset(instance, path);
modified++;
}
catch (System.Exception ex)
{
errors.Add($"{path}: Failed to save - {ex.Message}");
}
}
PrefabUtility.UnloadPrefabContents(instance);
}
}
finally
{
AssetDatabase.StopAssetEditing();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
string message = $"Scanned: {scanned}\nModified: {modified}";
if (errors.Count > 0)
{
message += $"\n\nErrors ({errors.Count}):\n" + string.Join("\n", errors.GetRange(0, Mathf.Min(errors.Count, 5)));
if (errors.Count > 5)
message += $"\n... and {errors.Count - 5} more";
}
EditorUtility.DisplayDialog("Remove Invalid Meshes - Finished", message, "OK");
}
static bool ShouldRemoveMeshCollider(MeshCollider mc, out string reason)
{
reason = null;
if (mc == null)
{
reason = "MeshCollider is null";
return true;
}
Mesh mesh = mc.sharedMesh;
if (mesh == null)
{
reason = "Mesh is null";
return true;
}
Vector3 size = mesh.bounds.size;
if (size.x < MinBoundsSize || size.y < MinBoundsSize || size.z < MinBoundsSize)
{
reason = $"Mesh bounds too small (x:{size.x:F3}, y:{size.y:F3}, z:{size.z:F3})";
return true;
}
return false;
}
}