Skip to content

Instantly share code, notes, and snippets.

@habedi
Last active April 29, 2025 02:21
Show Gist options
  • Select an option

  • Save habedi/de36bcc68aa1b79657650db579476648 to your computer and use it in GitHub Desktop.

Select an option

Save habedi/de36bcc68aa1b79657650db579476648 to your computer and use it in GitHub Desktop.
Finding dangling assets in Unity #unity #utilities #script

This is a minimal version of Unity-Dependencies-Hunterin less than 100 lines of C# code. It scans all assets in the project, checks their dependencies, and lists those that are not referenced by any other asset.

Put it in the Assets/Editor directory and run it from Tools -> Unreferenced Assets Finder.

using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class UnreferencedAssetsFinder : EditorWindow
{
    private List<string> _unreferencedAssets;
    private Vector2 _scroll;

    [MenuItem("Tools/Unreferenced Assets Finder")]
    public static void ShowWindow()
    {
        GetWindow<UnreferencedAssetsFinder>("Unreferenced Assets");
    }

    private void OnGUI()
    {
        if (GUILayout.Button("Scan Project"))
        {
            FindUnreferencedAssets();
        }

        if (_unreferencedAssets == null) return;

        GUILayout.Label($"Found {_unreferencedAssets.Count} unreferenced assets");
        _scroll = GUILayout.BeginScrollView(_scroll);

        foreach (var assetPath in _unreferencedAssets)
        {
            GUILayout.BeginHorizontal();
            if (GUILayout.Button(Path.GetFileName(assetPath), GUILayout.Width(250)))
            {
                Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(assetPath);
            }
            GUILayout.Label(assetPath);
            GUILayout.EndHorizontal();
        }

        GUILayout.EndScrollView();
    }

    private void FindUnreferencedAssets()
    {
        var allAssets = AssetDatabase.GetAllAssetPaths()
            .Where(p => p.StartsWith("Assets/") && !Directory.Exists(p))
            .ToList();

        var dependencies = new HashSet<string>();

        for (int i = 0; i < allAssets.Count; i++)
        {
            EditorUtility.DisplayProgressBar("Scanning", allAssets[i], (float)i / allAssets.Count);
            foreach (var dep in AssetDatabase.GetDependencies(allAssets[i], false))
            {
                if (dep != allAssets[i])
                    dependencies.Add(dep);
            }
        }

        EditorUtility.ClearProgressBar();

        _unreferencedAssets = allAssets
            .Where(a => !dependencies.Contains(a) && IsValidAsset(a))
            .OrderBy(a => a)
            .ToList();
    }

    private bool IsValidAsset(string path)
    {
        var type = AssetDatabase.GetMainAssetTypeAtPath(path);
        if (type == typeof(DefaultAsset) || type == typeof(MonoScript) || type == typeof(SceneAsset)) return false;
        if (path.Contains("/Editor/") || path.Contains("/Resources/")) return false;
        if (path.EndsWith(".asmdef") || path.EndsWith(".json") || path.EndsWith(".xml") || path.EndsWith(".txt")) return false;
        return true;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment