From 1d0c0ee7cbe39a87d0daa2e38d2d38285d654e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= Date: Fri, 3 Jan 2025 10:23:27 +0800 Subject: [PATCH] update asset bundle collector --- .../AssetDependencyCache.cs | 237 +---------------- .../AssetDependencyDatabase.cs | 240 ++++++++++++++++++ .../AssetDependencyDatabase.cs.meta | 11 + 3 files changed, 258 insertions(+), 230 deletions(-) create mode 100644 Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs create mode 100644 Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs.meta diff --git a/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyCache.cs b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyCache.cs index 7d1020a5..6da69a2d 100644 --- a/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyCache.cs +++ b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyCache.cs @@ -10,246 +10,23 @@ namespace YooAsset.Editor { public class AssetDependencyCache { - /// - /// 资源依赖缓存数据库 - /// - private class CacheDatabase - { - private class CacheInfo - { - /// - /// 此哈希函数会聚合了以下内容:源资源路径、源资源、元文件、目标平台以及导入器版本。 - /// 如果此哈希值发送变化,则说明导入资源可能已更改,因此应重新搜集依赖关系。 - /// - public string DependHash; - - /// - /// 直接依赖资源的GUID列表 - /// - public List DependGUIDs = new List(); - } - - private string _databaseFilePath; - private readonly Dictionary _database = new Dictionary(100000); - - /// - /// 创建数据库 - /// - public void CreateDatabase(string databaseFilePath, bool useCacheDatabase) - { - _databaseFilePath = databaseFilePath; - _database.Clear(); - - try - { - if (useCacheDatabase && File.Exists(databaseFilePath)) - { - // 解析缓存文件 - using var stream = File.OpenRead(databaseFilePath); - using var reader = new BinaryReader(stream); - var count = reader.ReadInt32(); - for (int i = 0; i < count; i++) - { - var assetPath = reader.ReadString(); - var cacheInfo = new CacheInfo - { - DependHash = reader.ReadString(), - DependGUIDs = ReadStringList(reader), - }; - _database.Add(assetPath, cacheInfo); - } - - // 移除无效资源 - List removeList = new List(10000); - foreach (var cacheInfoPair in _database) - { - var assetPath = cacheInfoPair.Key; - var assetGUID = AssetDatabase.AssetPathToGUID(assetPath); - if (string.IsNullOrEmpty(assetGUID)) - { - removeList.Add(assetPath); - } - } - foreach (var assetPath in removeList) - { - _database.Remove(assetPath); - } - } - } - catch (Exception ex) - { - ClearCache(true); - Debug.LogError($"Failed to load cache database : {ex.Message}"); - } - - // 查找新增或变动资源 - var allAssetPaths = AssetDatabase.GetAllAssetPaths(); - foreach (var assetPath in allAssetPaths) - { - if (_database.TryGetValue(assetPath, out CacheInfo cacheInfo)) - { - var dependHash = AssetDatabase.GetAssetDependencyHash(assetPath); - if (dependHash.ToString() != cacheInfo.DependHash) - { - _database[assetPath] = CreateCacheInfo(assetPath); - } - } - else - { - var newCacheInfo = CreateCacheInfo(assetPath); - _database.Add(assetPath, newCacheInfo); - } - } - } - - /// - /// 保存缓存文件 - /// - public void SaveCacheFile() - { - if (File.Exists(_databaseFilePath)) - File.Delete(_databaseFilePath); - - try - { - using var stream = File.Create(_databaseFilePath); - using var writer = new BinaryWriter(stream); - writer.Write(_database.Count); - foreach (var assetPair in _database) - { - string assetPath = assetPair.Key; - var assetInfo = assetPair.Value; - writer.Write(assetPath); - writer.Write(assetInfo.DependHash); - WriteStringList(writer, assetInfo.DependGUIDs); - } - writer.Flush(); - } - catch (Exception ex) - { - Debug.LogError($"Failed to save cache database : {ex.Message}"); - } - } - - /// - /// 清理缓存数据 - /// - public void ClearCache(bool clearDatabaseFile) - { - if (clearDatabaseFile) - { - if (File.Exists(_databaseFilePath)) - File.Delete(_databaseFilePath); - } - - _database.Clear(); - } - - /// - /// 获取资源的依赖列表 - /// - public string[] GetDependencies(string assetPath, bool recursive) - { - // 注意:AssetDatabase.GetDependencies()方法返回结果里会踢出丢失文件! - // 注意:AssetDatabase.GetDependencies()方法返回结果里会包含主资源路径! - - // 注意:机制上不允许存在未收录的资源 - if (_database.ContainsKey(assetPath) == false) - { - throw new Exception($"Fatal : can not found cache info : {assetPath}"); - } - - var result = new HashSet { assetPath }; - CollectDependencies(assetPath, result, recursive); - - // 注意:AssetDatabase.GetDependencies保持一致,将主资源添加到依赖列表最前面 - return result.ToArray(); - } - private void CollectDependencies(string assetPath, HashSet result, bool recursive) - { - if (_database.TryGetValue(assetPath, out var cacheInfo) == false) - { - throw new Exception($"Fatal : can not found cache info : {assetPath}"); - } - - foreach (var dependGUID in cacheInfo.DependGUIDs) - { - string dependAssetPath = AssetDatabase.GUIDToAssetPath(dependGUID); - if (string.IsNullOrEmpty(dependAssetPath)) - continue; - - // 如果是文件夹资源 - if (AssetDatabase.IsValidFolder(dependAssetPath)) - continue; - - // 如果已经收集过 - if (result.Contains(dependAssetPath)) - continue; - - result.Add(dependAssetPath); - - // 递归收集依赖 - if (recursive) - CollectDependencies(dependAssetPath, result, recursive); - } - } - - private List ReadStringList(BinaryReader reader) - { - var count = reader.ReadInt32(); - var values = new List(count); - for (int i = 0; i < count; i++) - { - values.Add(reader.ReadString()); - } - return values; - } - private void WriteStringList(BinaryWriter writer, List values) - { - writer.Write(values.Count); - foreach (var value in values) - { - writer.Write(value); - } - } - private CacheInfo CreateCacheInfo(string assetPath) - { - var dependHash = AssetDatabase.GetAssetDependencyHash(assetPath); - var dependAssetPaths = AssetDatabase.GetDependencies(assetPath, false); - var dependGUIDs = new List(); - foreach (var dependAssetPath in dependAssetPaths) - { - string guid = AssetDatabase.AssetPathToGUID(dependAssetPath); - if (string.IsNullOrEmpty(guid) == false) - { - dependGUIDs.Add(guid); - } - } - - var cacheInfo = new CacheInfo(); - cacheInfo.DependHash = dependHash.ToString(); - cacheInfo.DependGUIDs = dependGUIDs; - return cacheInfo; - } - } - - private readonly CacheDatabase _database; + private readonly AssetDependencyDatabase _database; /// /// 初始化资源依赖缓存系统 /// - public AssetDependencyCache(bool useCacheDatabase) + public AssetDependencyCache(bool useAssetDependencyDB) { - if (useCacheDatabase) + if (useAssetDependencyDB) Debug.Log("Use asset dependency database !"); string databaseFilePath = "Library/AssetDependencyDB"; - _database = new CacheDatabase(); - _database.CreateDatabase(databaseFilePath, useCacheDatabase); + _database = new AssetDependencyDatabase(); + _database.CreateDatabase(useAssetDependencyDB, databaseFilePath); - if (useCacheDatabase) + if (useAssetDependencyDB) { - _database.SaveCacheFile(); + _database.SaveDatabase(); } } diff --git a/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs new file mode 100644 index 00000000..50aea16c --- /dev/null +++ b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor; +using UnityEngine; + +namespace YooAsset.Editor +{ + /// + /// 资源依赖数据库 + /// + public class AssetDependencyDatabase + { + private const string FILE_VERSION = "1.0"; + + private class DependencyInfo + { + /// + /// 此哈希函数会聚合了以下内容:源资源路径、源资源、元文件、目标平台以及导入器版本。 + /// 如果此哈希值发送变化,则说明导入资源可能已更改,因此应重新搜集依赖关系。 + /// + public string DependHash; + + /// + /// 直接依赖资源的GUID列表 + /// + public List DependGUIDs = new List(); + } + + private string _databaseFilePath; + private readonly Dictionary _database = new Dictionary(100000); + + /// + /// 创建缓存数据库 + /// + public void CreateDatabase(bool readCacheDatabaseFile, string databaseFilePath) + { + _databaseFilePath = databaseFilePath; + _database.Clear(); + + try + { + if (readCacheDatabaseFile && File.Exists(databaseFilePath)) + { + // 解析缓存文件 + using var stream = File.OpenRead(databaseFilePath); + using var reader = new BinaryReader(stream); + string fileVersion = reader.ReadString(); + if (fileVersion != FILE_VERSION) + throw new Exception("The database file version not match !"); + + var count = reader.ReadInt32(); + for (int i = 0; i < count; i++) + { + var assetPath = reader.ReadString(); + var cacheInfo = new DependencyInfo + { + DependHash = reader.ReadString(), + DependGUIDs = ReadStringList(reader), + }; + _database.Add(assetPath, cacheInfo); + } + + // 移除无效资源 + List removeList = new List(10000); + foreach (var cacheInfoPair in _database) + { + var assetPath = cacheInfoPair.Key; + var assetGUID = AssetDatabase.AssetPathToGUID(assetPath); + if (string.IsNullOrEmpty(assetGUID)) + { + removeList.Add(assetPath); + } + } + foreach (var assetPath in removeList) + { + _database.Remove(assetPath); + } + } + } + catch (Exception ex) + { + ClearDatabase(true); + Debug.LogError($"Failed to load cache database : {ex.Message}"); + } + + // 查找新增或变动资源 + var allAssetPaths = AssetDatabase.GetAllAssetPaths(); + foreach (var assetPath in allAssetPaths) + { + if (_database.TryGetValue(assetPath, out DependencyInfo cacheInfo)) + { + var dependHash = AssetDatabase.GetAssetDependencyHash(assetPath); + if (dependHash.ToString() != cacheInfo.DependHash) + { + _database[assetPath] = CreateDependencyInfo(assetPath); + } + } + else + { + var newCacheInfo = CreateDependencyInfo(assetPath); + _database.Add(assetPath, newCacheInfo); + } + } + } + + /// + /// 保存缓存数据库 + /// + public void SaveDatabase() + { + if (File.Exists(_databaseFilePath)) + File.Delete(_databaseFilePath); + + try + { + using var stream = File.Create(_databaseFilePath); + using var writer = new BinaryWriter(stream); + writer.Write(FILE_VERSION); + writer.Write(_database.Count); + foreach (var assetPair in _database) + { + string assetPath = assetPair.Key; + var assetInfo = assetPair.Value; + writer.Write(assetPath); + writer.Write(assetInfo.DependHash); + WriteStringList(writer, assetInfo.DependGUIDs); + } + writer.Flush(); + } + catch (Exception ex) + { + Debug.LogError($"Failed to save cache database : {ex.Message}"); + } + } + + /// + /// 清理缓存数据库 + /// + public void ClearDatabase(bool deleteDatabaseFile) + { + if (deleteDatabaseFile) + { + if (File.Exists(_databaseFilePath)) + File.Delete(_databaseFilePath); + } + + _database.Clear(); + } + + /// + /// 获取资源的依赖列表 + /// + public string[] GetDependencies(string assetPath, bool recursive) + { + // 注意:AssetDatabase.GetDependencies()方法返回结果里会踢出丢失文件! + // 注意:AssetDatabase.GetDependencies()方法返回结果里会包含主资源路径! + + // 注意:机制上不允许存在未收录的资源 + if (_database.ContainsKey(assetPath) == false) + { + throw new Exception($"Fatal : can not found cache info : {assetPath}"); + } + + var result = new HashSet { assetPath }; + CollectDependencies(assetPath, result, recursive); + + // 注意:AssetDatabase.GetDependencies保持一致,将主资源添加到依赖列表最前面 + return result.ToArray(); + } + private void CollectDependencies(string assetPath, HashSet result, bool recursive) + { + if (_database.TryGetValue(assetPath, out var cacheInfo) == false) + { + throw new Exception($"Fatal : can not found cache info : {assetPath}"); + } + + foreach (var dependGUID in cacheInfo.DependGUIDs) + { + string dependAssetPath = AssetDatabase.GUIDToAssetPath(dependGUID); + if (string.IsNullOrEmpty(dependAssetPath)) + continue; + + // 如果是文件夹资源 + if (AssetDatabase.IsValidFolder(dependAssetPath)) + continue; + + // 如果已经收集过 + if (result.Contains(dependAssetPath)) + continue; + + result.Add(dependAssetPath); + + // 递归收集依赖 + if (recursive) + CollectDependencies(dependAssetPath, result, recursive); + } + } + + private List ReadStringList(BinaryReader reader) + { + var count = reader.ReadInt32(); + var values = new List(count); + for (int i = 0; i < count; i++) + { + values.Add(reader.ReadString()); + } + return values; + } + private void WriteStringList(BinaryWriter writer, List values) + { + writer.Write(values.Count); + foreach (var value in values) + { + writer.Write(value); + } + } + private DependencyInfo CreateDependencyInfo(string assetPath) + { + var dependHash = AssetDatabase.GetAssetDependencyHash(assetPath); + var dependAssetPaths = AssetDatabase.GetDependencies(assetPath, false); + var dependGUIDs = new List(); + foreach (var dependAssetPath in dependAssetPaths) + { + string guid = AssetDatabase.AssetPathToGUID(dependAssetPath); + if (string.IsNullOrEmpty(guid) == false) + { + dependGUIDs.Add(guid); + } + } + + var cacheInfo = new DependencyInfo(); + cacheInfo.DependHash = dependHash.ToString(); + cacheInfo.DependGUIDs = dependGUIDs; + return cacheInfo; + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs.meta b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs.meta new file mode 100644 index 00000000..e48d3471 --- /dev/null +++ b/Assets/YooAsset/Editor/AssetBundleCollector/AssetDependencyDatabase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38f3f2338cca06a42a0f845df9fbb563 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: