特定の型の依存情報のみを高速で取得したい案件があったので,
JSONで依存情報を保存しておき, 必要な時にデシリアライズして使用します.
ソースコード
using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace DependenceData { public class DependenceData : AssetPostprocessor { private const string ROOT_DIR_NAME = "DependenceData"; private static List<Type> ObserveType = new List<Type>() { typeof(MonoScript), typeof(GameObject), }; [MenuItem("Func/DependenceData")] private static void Execute() { foreach (var type in ObserveType) { Initialize(type); } } public static void Initialize(Type type) { var guids = AssetDatabase.FindAssets($"t: {type.Name}").ToList(); UpdateGuids(guids); } private static void AddGuid(string addedGuid) { // 依存先の被依存リストに追加. var guidList = GetDependenciesAsGuidByGuid(addedGuid); foreach (var guid in guidList) { TryGetSavedGuids(guid, out var savedGuids); savedGuids ??= new Guids(); // ファイルが無ければ作成. savedGuids.AddFromDependents(addedGuid); Save(guid, savedGuids); } // 依存先情報を保存. var addedGuids = new Guids(); addedGuids.UpdateToDependencies(guidList); Save(addedGuid, addedGuids); } private static void RemoveGuids(List<string> removedGuidList) { if (removedGuidList == null) { return; } foreach (var removedGuid in removedGuidList) { // 依存先の被依存リストから削除. TryGetSavedGuids(removedGuid, out var guids); guids ??= new Guids(); foreach (var guid in guids.m_ToDependencies) { if (TryGetSavedGuids(guid, out var savedGuids)) { savedGuids.RemoveFromDependents(removedGuid); Save(guid, savedGuids); } } DeleteSaveData(removedGuid); } } private static void UpdateGuids(List<string> guidList) { if (guidList == null) { return; } foreach (var guid in guidList) { var dependencies = GetDependenciesAsGuidByGuid(guid); // 既に管理対象の guid であれば, 関連ファイルを更新する. if (TryGetSavedGuids(guid, out var savedGuids)) { foreach (var added in dependencies) { // 依存先の被依存リストに書き込む. TryGetSavedGuids(added, out var guids); guids ??= new Guids(); guids.AddFromDependents(guid); Save(added, guids); } foreach (var removed in savedGuids.GetExceptedToDependencies(dependencies)) { // 依存先の被依存から消す. if (TryGetSavedGuids(removed, out var guids)) { guids.RemoveFromDependents(guid); Save(removed, guids); } } savedGuids.UpdateToDependencies(dependencies); Save(guid, savedGuids); } else { // 新規追加の guid. AddGuid(guid); } } } private static IEnumerable<string> GetDependenciesAsGuidByGuid(string guid) { var path = AssetDatabase.GUIDToAssetPath(guid); return AssetDatabase.GetDependencies(path, false) .Select(path => AssetDatabase.AssetPathToGUID(path)); } public static List<string> GetFromDependentsByPath(string path) { return GetFromDepenets(AssetDatabase.AssetPathToGUID(path)); } public static List<string> GetFromDepenets(string guid) { TryGetSavedGuids(guid, out var guids); return guids.m_FromDependents ?? new List<string>(); } private static bool TryGetSavedGuids(string guid, out Guids guids) { guids = null; var filePath = GetGuidPath(guid); if (File.Exists(filePath)) { var json = File.ReadAllText(filePath); guids = JsonUtility.FromJson<Guids>(json); return true; } return false; } private static void Save(string fileGuid, Guids guids) { var filePath = GetGuidPath(fileGuid); CreateDirectory(filePath); var json = JsonUtility.ToJson(guids, true); File.WriteAllText(filePath, json); } private static void DeleteSaveData(string guid) { var path = GetGuidPath(guid); if (!File.Exists(path)) { return; } File.Delete(path); } private static string GetRootPath() { var projectPath = Directory.GetParent(Application.dataPath).FullName.Replace("\\", "/"); return $"{projectPath}/{ROOT_DIR_NAME}"; } private static string GetGuidPath(string guid) { return $"{GetRootPath()}/{guid.Substring(0, 2)}/{guid}.json"; } private static void CreateDirectory(string filePath) { var dir = Directory.GetParent(filePath).FullName.Replace("\\", "/"); if (Directory.Exists(dir)) { return; } Directory.CreateDirectory(dir); } private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { var importedAssetsGuids = importedAssets .Where(path => ObserveType.Contains(AssetDatabase.GetMainAssetTypeAtPath(path))) .Select(path => AssetDatabase.AssetPathToGUID(path)) .ToList(); UpdateGuids(importedAssetsGuids); var deletedAssetsGuids = deletedAssets .Where(path => ObserveType.Contains(AssetDatabase.GetMainAssetTypeAtPath(path))) .Select(path => AssetDatabase.AssetPathToGUID(path)) .ToList(); RemoveGuids(deletedAssetsGuids); } [Serializable] private class Guids { // 被依存 public List<string> m_FromDependents = new(); // 依存先 public List<string> m_ToDependencies = new(); public Guids() { } // 非依存を追加 public void AddFromDependents(string guid) { if (m_FromDependents.Contains(guid)) { return; } m_FromDependents.Add(guid); } // 被依存を削除 public void RemoveFromDependents(string guid) { m_FromDependents.Remove(guid); } // 被依存を削除 public void RemoveFromDependents(Guids guids) { if (guids == null) { return; } foreach (var guid in guids.m_FromDependents) { m_FromDependents.Remove(guid); } } // 依存先を更新. public void UpdateToDependencies(IEnumerable<string> guidList) { if (guidList == null) { return; } m_ToDependencies.Clear(); m_ToDependencies.AddRange(guidList); } // 非依存・依存先を追加 public void Add(Guids guids) { if (guids == null) { return; } foreach (var guid in guids.m_FromDependents) { AddFromDependents(guid); } UpdateToDependencies(guids.m_ToDependencies); } // guidList にのみ存在する guid リストを返す public IEnumerable<string> GetExceptedToDependencies(IEnumerable<string> guidList) { if (guidList == null) { return new List<string>(); } return m_ToDependencies.Except(guidList); } } } }