Unity扫描粒子系统丢失的材质

2026/01 26 16:01
using UnityEditor;
using System.Text;
using UnityEngine;
using System.Collections.Generic;

public static class MaterialLostCheckTool
{
    [MenuItem("Tools/资源扫描工具/扫描粒子系统丢失的材质")]
    public static void CheckMaterialLost()
    {
        var allAssetPaths = AssetDatabase.GetAllAssetPaths();
        List<string> files = new List<string>();
        foreach(var assetPath in allAssetPaths)
        {
            if(!assetPath.EndsWith(".prefab", System.StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }
            files.Add(assetPath);
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0; i<files.Count; ++i)
        {
            var assetPath = files[i];
            CheckParticleSystem(assetPath, sb);
            EditorUtility.DisplayProgressBar("扫描", assetPath, (float)i / files.Count);
        }
        EditorUtility.ClearProgressBar();

        System.IO.File.WriteAllText("Tools/ParticleSystemLostMaterial.txt", sb.ToString());

    }

    private static bool CheckParticleSystem(string assetPath, StringBuilder sb)
    {
        var go = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
        if(go == null)
        {
            return false;
        }
        StringBuilder lostNames = new StringBuilder();
        var ps = go.GetComponentsInChildren<ParticleSystem>(true);
        foreach(var p in ps)
        {
            var psr = p.GetComponent<ParticleSystemRenderer>();
            if (psr == null)
            {
                continue;
            }
            if (!psr.enabled)
            {
                continue;
            }
            var idx = psr.sharedMaterials.Length - 1;
            if (psr.sharedMaterials[idx] == null)
            {
                lostNames.Append($"{p.gameObject.name}; ");
            }
        }
        if (lostNames.Length > 0)
        {
            sb.AppendLine($"{assetPath} = {lostNames}");
        }
        return true;
    }
}