源战役客户端
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

276 righe
9.1 KiB

4 settimane fa
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Runtime.Serialization.Formatters.Binary;
  6. using UnityEditor;
  7. using UnityEngine;
  8. public class ReferenceFinderData
  9. {
  10. //缓存路径
  11. private const string CACHE_PATH = "Library/ReferenceFinderCache";
  12. private const string CACHE_VERSION = "V1";
  13. //资源引用信息字典
  14. public Dictionary<string, AssetDescription> assetDict = new Dictionary<string, AssetDescription>();
  15. //收集资源引用信息并更新缓存
  16. public void CollectDependenciesInfo()
  17. {
  18. try
  19. {
  20. ReadFromCache();
  21. var allAssets = AssetDatabase.GetAllAssetPaths();
  22. int totalCount = allAssets.Length;
  23. for (int i = 0; i < allAssets.Length; i++)
  24. {
  25. //每遍历100个Asset,更新一下进度条,同时对进度条的取消操作进行处理
  26. if ((i % 100 == 0) && EditorUtility.DisplayCancelableProgressBar("Refresh", string.Format("Collecting {0} assets", i), (float)i / totalCount))
  27. {
  28. EditorUtility.ClearProgressBar();
  29. return;
  30. }
  31. if (File.Exists(allAssets[i]))
  32. ImportAsset(allAssets[i]);
  33. if (i % 2000 == 0)
  34. GC.Collect();
  35. }
  36. //将信息写入缓存
  37. EditorUtility.DisplayCancelableProgressBar("Refresh", "Write to cache", 1f);
  38. WriteToChache();
  39. //生成引用数据
  40. EditorUtility.DisplayCancelableProgressBar("Refresh", "Generating asset reference info", 1f);
  41. UpdateReferenceInfo();
  42. EditorUtility.ClearProgressBar();
  43. }
  44. catch(Exception e)
  45. {
  46. Debug.LogError(e);
  47. EditorUtility.ClearProgressBar();
  48. }
  49. }
  50. //通过依赖信息更新引用信息
  51. private void UpdateReferenceInfo()
  52. {
  53. foreach(var asset in assetDict)
  54. {
  55. foreach(var assetGuid in asset.Value.dependencies)
  56. {
  57. assetDict[assetGuid].references.Add(asset.Key);
  58. }
  59. }
  60. }
  61. //生成并加入引用信息
  62. private void ImportAsset(string path)
  63. {
  64. if (!path.StartsWith("Assets/"))
  65. return;
  66. //通过path获取guid进行储存
  67. string guid = AssetDatabase.AssetPathToGUID(path);
  68. //获取该资源的最后修改时间,用于之后的修改判断
  69. Hash128 assetDependencyHash = AssetDatabase.GetAssetDependencyHash(path);
  70. //如果assetDict没包含该guid或包含了修改时间不一样则需要更新
  71. if (!assetDict.ContainsKey(guid) || assetDict[guid].assetDependencyHash != assetDependencyHash.ToString())
  72. {
  73. //将每个资源的直接依赖资源转化为guid进行储存
  74. var guids = AssetDatabase.GetDependencies(path, false).
  75. Select(p => AssetDatabase.AssetPathToGUID(p)).
  76. ToList();
  77. //生成asset依赖信息,被引用需要在所有的asset依赖信息生成完后才能生成
  78. AssetDescription ad = new AssetDescription();
  79. ad.name = Path.GetFileNameWithoutExtension(path);
  80. ad.path = path;
  81. ad.assetDependencyHash = assetDependencyHash.ToString();
  82. ad.dependencies = guids;
  83. if (assetDict.ContainsKey(guid))
  84. assetDict[guid] = ad;
  85. else
  86. assetDict.Add(guid, ad);
  87. }
  88. }
  89. //读取缓存信息
  90. public bool ReadFromCache()
  91. {
  92. assetDict.Clear();
  93. if (!File.Exists(CACHE_PATH))
  94. {
  95. return false;
  96. }
  97. var serializedGuid = new List<string>();
  98. var serializedDependencyHash = new List<string>();
  99. var serializedDenpendencies = new List<int[]>();
  100. //反序列化数据
  101. FileStream fs = File.OpenRead(CACHE_PATH);
  102. try
  103. {
  104. BinaryFormatter bf = new BinaryFormatter();
  105. string cacheVersion = (string) bf.Deserialize(fs);
  106. if (cacheVersion != CACHE_VERSION)
  107. {
  108. return false;
  109. }
  110. EditorUtility.DisplayCancelableProgressBar("Import Cache", "Reading Cache", 0);
  111. serializedGuid = (List<string>) bf.Deserialize(fs);
  112. serializedDependencyHash = (List<string>) bf.Deserialize(fs);
  113. serializedDenpendencies = (List<int[]>) bf.Deserialize(fs);
  114. EditorUtility.ClearProgressBar();
  115. }
  116. catch
  117. {
  118. //兼容旧版本序列化格式
  119. return false;
  120. }
  121. finally
  122. {
  123. fs.Close();
  124. }
  125. for (int i = 0; i < serializedGuid.Count; ++i)
  126. {
  127. string path = AssetDatabase.GUIDToAssetPath(serializedGuid[i]);
  128. if (!string.IsNullOrEmpty(path))
  129. {
  130. var ad = new AssetDescription();
  131. ad.name = Path.GetFileNameWithoutExtension(path);
  132. ad.path = path;
  133. ad.assetDependencyHash = serializedDependencyHash[i];
  134. assetDict.Add(serializedGuid[i], ad);
  135. }
  136. }
  137. for(int i = 0; i < serializedGuid.Count; ++i)
  138. {
  139. string guid = serializedGuid[i];
  140. if (assetDict.ContainsKey(guid))
  141. {
  142. var guids = serializedDenpendencies[i].
  143. Select(index => serializedGuid[index]).
  144. Where(g => assetDict.ContainsKey(g)).
  145. ToList();
  146. assetDict[guid].dependencies = guids;
  147. }
  148. }
  149. UpdateReferenceInfo();
  150. return true;
  151. }
  152. //写入缓存
  153. private void WriteToChache()
  154. {
  155. if (File.Exists(CACHE_PATH))
  156. File.Delete(CACHE_PATH);
  157. var serializedGuid = new List<string>();
  158. var serializedDependencyHash = new List<string>();
  159. var serializedDenpendencies = new List<int[]>();
  160. //辅助映射字典
  161. var guidIndex = new Dictionary<string, int>();
  162. //序列化
  163. using (FileStream fs = File.OpenWrite(CACHE_PATH))
  164. {
  165. foreach (var pair in assetDict)
  166. {
  167. guidIndex.Add(pair.Key, guidIndex.Count);
  168. serializedGuid.Add(pair.Key);
  169. serializedDependencyHash.Add(pair.Value.assetDependencyHash);
  170. }
  171. foreach(var guid in serializedGuid)
  172. {
  173. //使用 Where 子句过滤目录
  174. int[] indexes = assetDict[guid].dependencies.
  175. Where(s => guidIndex.ContainsKey(s)).
  176. Select(s => guidIndex[s]).ToArray();
  177. serializedDenpendencies.Add(indexes);
  178. }
  179. BinaryFormatter bf = new BinaryFormatter();
  180. bf.Serialize(fs, CACHE_VERSION);
  181. bf.Serialize(fs, serializedGuid);
  182. bf.Serialize(fs, serializedDependencyHash);
  183. bf.Serialize(fs, serializedDenpendencies);
  184. }
  185. }
  186. //更新引用信息状态
  187. public void UpdateAssetState(string guid)
  188. {
  189. AssetDescription ad;
  190. if (assetDict.TryGetValue(guid,out ad) && ad.state != AssetState.NODATA)
  191. {
  192. if (File.Exists(ad.path))
  193. {
  194. //修改时间与记录的不同为修改过的资源
  195. if (ad.assetDependencyHash != AssetDatabase.GetAssetDependencyHash(ad.path).ToString())
  196. {
  197. ad.state = AssetState.CHANGED;
  198. }
  199. else
  200. {
  201. //默认为普通资源
  202. ad.state = AssetState.NORMAL;
  203. }
  204. }
  205. //不存在为丢失
  206. else
  207. {
  208. ad.state = AssetState.MISSING;
  209. }
  210. }
  211. //字典中没有该数据
  212. else if(!assetDict.TryGetValue(guid, out ad))
  213. {
  214. string path = AssetDatabase.GUIDToAssetPath(guid);
  215. ad = new AssetDescription();
  216. ad.name = Path.GetFileNameWithoutExtension(path);
  217. ad.path = path;
  218. ad.state = AssetState.NODATA;
  219. assetDict.Add(guid, ad);
  220. }
  221. }
  222. //根据引用信息状态获取状态描述
  223. public static string GetInfoByState(AssetState state)
  224. {
  225. if(state == AssetState.CHANGED)
  226. {
  227. return "<color=#F0672AFF>Changed</color>";
  228. }
  229. else if (state == AssetState.MISSING)
  230. {
  231. return "<color=#FF0000FF>Missing</color>";
  232. }
  233. else if(state == AssetState.NODATA)
  234. {
  235. return "<color=#FFE300FF>No Data</color>";
  236. }
  237. return "Normal";
  238. }
  239. public class AssetDescription
  240. {
  241. public string name = "";
  242. public string path = "";
  243. public string assetDependencyHash;
  244. public List<string> dependencies = new List<string>();
  245. public List<string> references = new List<string>();
  246. public AssetState state = AssetState.NORMAL;
  247. }
  248. public enum AssetState
  249. {
  250. NORMAL,
  251. CHANGED,
  252. MISSING,
  253. NODATA,
  254. }
  255. }