using System; using UnityEngine; using System.Collections.Generic; using System.Diagnostics; using Debug = UnityEngine.Debug; using Object = UnityEngine.Object; #if UNITY_EDITOR using UnityEditor; #endif namespace Jovian.Utilities { public static class AssetUtility { public static TAsset FindAssetInProject(string assetName = "") where TAsset : Object { #if UNITY_EDITOR var filter = $"t:{typeof(TAsset).Name} {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (asset != null) { return asset; } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return default(TAsset); } public static Object FindAssetInProject(Type assetType, string assetName = "") { #if UNITY_EDITOR var filter = $"t:{assetType.Name} {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (asset != null) { return asset; } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return default(Object); } public static List FindAllAssetsInProject(string assetName = "") where TAsset : Object { var list = new List(); #if UNITY_EDITOR var filter = $"t:{typeof(TAsset).Name} {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (asset != null) { list.Add(asset); } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return list; } public static List FindAllAssetsInProject(Type assetType, string assetName = "") { var list = new List(); #if UNITY_EDITOR var filter = $"t:{assetType.Name} {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (asset != null) { list.Add(asset); } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return list; } public static List FindAllObjectsInProject(Type objectType, string filter) { List list = new List(); #if UNITY_EDITOR string[] guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { string path = AssetDatabase.GUIDToAssetPath(guid); Object asset = AssetDatabase.LoadAssetAtPath(path); if (typeof(Component).IsAssignableFrom(objectType) && TryGetTypeObjectWithPrefab(asset, objectType, out Component _)) { list.Add(asset); } else if (asset.GetType().IsAssignableFrom(objectType)) { list.Add(asset); } else if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return list; } // Prefabs public static TAsset FindPrefabInProject(string assetName = "") where TAsset : Component { #if UNITY_EDITOR var filter = $"t:Prefab {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (TryGetTypeObjectWithPrefab(asset, out TAsset component)) { return component; } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif Debug.LogError($"Failed to find asset '{assetName}' <{typeof(TAsset)}>"); return default(TAsset); } public static Object FindPrefabInProject(Type assetType, string assetName = "") { #if UNITY_EDITOR var filter = $"t:Prefab {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (TryGetTypeObjectWithPrefab(asset, assetType, out Component component)) { return component; } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return default(Object); } public static List FindAllPrefabsInProject(string assetName = "") where TAsset : Component { var list = new List(); #if UNITY_EDITOR var filter = $"t:Prefab {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (TryGetTypeObjectWithPrefab(asset, out TAsset component)) { list.Add(component); } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return list; } public static List FindAllPrefabsInProject(Type assetType, string assetName = "") { var list = new List(); #if UNITY_EDITOR var filter = $"t:Prefab {assetName}"; var guids = AssetDatabase.FindAssets(filter); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath(path); if (TryGetTypeObjectWithPrefab(asset, assetType, out Component component)) { list.Add(component); } else { if (ShouldUnloadAsset(asset)) { Resources.UnloadAsset(asset); } } } #else Debug.LogError("AssetUtility should not be called in non-Editor mode"); #endif return list; } // Util #if UNITY_EDITOR public static bool ShouldUnloadAsset(Object asset) { if (asset == null) { return false; } return !(asset is GameObject or Component or AssetBundle || PrefabUtility.GetPrefabAssetType(asset) != PrefabAssetType.NotAPrefab); } private static bool TryGetTypeObjectWithPrefab(Object prefab, Type type, out Component component) { if (prefab != null && prefab is GameObject gameObject && gameObject.TryGetComponent(type, out component)) { return true; } component = default; return false; } private static bool TryGetTypeObjectWithPrefab(Object prefab, out TComponent component) where TComponent : Component { if (prefab != null && prefab is TComponent prefabAsComponent) { component = prefabAsComponent; return true; } if (prefab != null && prefab is GameObject gameObject && gameObject.TryGetComponent(out component)) { return true; } component = default; return false; } #endif } }