From b689754acfb6b2503631bbfb019cbbed04fd7b5f Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期四, 04 十二月 2025 09:19:51 +0800
Subject: [PATCH] 125 战斗 新增预加载资源编辑器查看状态功能
---
Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta | 11 +
Assets/Editor/Tool/BattlePreloadResWatcher.cs | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 407 insertions(+), 0 deletions(-)
diff --git a/Assets/Editor/Tool/BattlePreloadResWatcher.cs b/Assets/Editor/Tool/BattlePreloadResWatcher.cs
new file mode 100644
index 0000000..62657de
--- /dev/null
+++ b/Assets/Editor/Tool/BattlePreloadResWatcher.cs
@@ -0,0 +1,396 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System.Linq;
+
+/// <summary>
+/// 鎴樻枟棰勫姞杞借祫婧愮洃鎺х獥鍙�
+/// </summary>
+public class BattlePreloadResWatcher : EditorWindow
+{
+ private Vector2 scrollPosition;
+ private bool showSpineResources = true;
+ private bool showAudioResources = true;
+ private string filterText = "";
+ private bool autoRefresh = true;
+ private double lastRefreshTime = 0;
+ private const double AUTO_REFRESH_INTERVAL = 1.0; // 1绉掕嚜鍔ㄥ埛鏂�
+
+ private List<BattleCacheManager.ResourceReferenceView> spineResourceViews = new List<BattleCacheManager.ResourceReferenceView>();
+ private List<BattleCacheManager.ResourceReferenceView> audioResourceViews = new List<BattleCacheManager.ResourceReferenceView>();
+ private HashSet<string> allBattleGuids = new HashSet<string>();
+
+ private GUIStyle headerStyle;
+ private GUIStyle evenRowStyle;
+ private GUIStyle oddRowStyle;
+ private GUIStyle loadedStyle;
+ private GUIStyle unloadedStyle;
+
+ [MenuItem("Tools/鎴樻枟/棰勫姞杞借祫婧愮洃鎺�")]
+ public static void ShowWindow()
+ {
+ var window = GetWindow<BattlePreloadResWatcher>("鎴樻枟璧勬簮鐩戞帶");
+ window.minSize = new Vector2(800, 400);
+ window.Show();
+ }
+
+ private void OnEnable()
+ {
+ RefreshData();
+ }
+
+ private void OnGUI()
+ {
+ InitStyles();
+
+ // 椤堕儴宸ュ叿鏍�
+ DrawToolbar();
+
+ // 缁熻淇℃伅
+ DrawStatistics();
+
+ GUILayout.Space(5);
+
+ // 婊氬姩鍖哄煙
+ scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
+
+ // Spine璧勬簮
+ if (showSpineResources)
+ {
+ DrawResourceSection("Spine 璧勬簮", spineResourceViews);
+ }
+
+ GUILayout.Space(10);
+
+ // Audio璧勬簮
+ if (showAudioResources)
+ {
+ DrawResourceSection("Audio 璧勬簮", audioResourceViews);
+ }
+
+ EditorGUILayout.EndScrollView();
+
+ // 鑷姩鍒锋柊
+ if (autoRefresh && EditorApplication.timeSinceStartup - lastRefreshTime > AUTO_REFRESH_INTERVAL)
+ {
+ RefreshData();
+ lastRefreshTime = EditorApplication.timeSinceStartup;
+ Repaint();
+ }
+ }
+
+ private void InitStyles()
+ {
+ if (headerStyle == null)
+ {
+ headerStyle = new GUIStyle(EditorStyles.boldLabel)
+ {
+ fontSize = 14,
+ normal = { textColor = Color.white }
+ };
+
+ evenRowStyle = new GUIStyle(EditorStyles.label)
+ {
+ normal = { background = MakeTexture(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.1f)) }
+ };
+
+ oddRowStyle = new GUIStyle(EditorStyles.label)
+ {
+ normal = { background = MakeTexture(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.3f)) }
+ };
+
+ loadedStyle = new GUIStyle(EditorStyles.label)
+ {
+ normal = { textColor = Color.green }
+ };
+
+ unloadedStyle = new GUIStyle(EditorStyles.label)
+ {
+ normal = { textColor = Color.red }
+ };
+ }
+ }
+
+ private Texture2D MakeTexture(int width, int height, Color color)
+ {
+ Color[] pixels = new Color[width * height];
+ for (int i = 0; i < pixels.Length; i++)
+ {
+ pixels[i] = color;
+ }
+
+ Texture2D texture = new Texture2D(width, height);
+ texture.SetPixels(pixels);
+ texture.Apply();
+ return texture;
+ }
+
+ private void DrawToolbar()
+ {
+ EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
+
+ if (GUILayout.Button("鍒锋柊鏁版嵁", EditorStyles.toolbarButton, GUILayout.Width(80)))
+ {
+ RefreshData();
+ }
+
+ autoRefresh = GUILayout.Toggle(autoRefresh, "鑷姩鍒锋柊", EditorStyles.toolbarButton, GUILayout.Width(80));
+
+ GUILayout.Space(10);
+
+ showSpineResources = GUILayout.Toggle(showSpineResources, "鏄剧ずSpine", EditorStyles.toolbarButton, GUILayout.Width(80));
+ showAudioResources = GUILayout.Toggle(showAudioResources, "鏄剧ずAudio", EditorStyles.toolbarButton, GUILayout.Width(80));
+
+ GUILayout.Space(10);
+
+ GUILayout.Label("绛涢��:", GUILayout.Width(40));
+ filterText = GUILayout.TextField(filterText, EditorStyles.toolbarTextField, GUILayout.Width(200));
+
+ GUILayout.FlexibleSpace();
+
+ if (GUILayout.Button("娓呯┖缂撳瓨", EditorStyles.toolbarButton, GUILayout.Width(80)))
+ {
+ if (EditorUtility.DisplayDialog("纭", "纭畾瑕佹竻绌烘墍鏈夋垬鏂楄祫婧愮紦瀛樺悧锛�", "纭畾", "鍙栨秷"))
+ {
+ BattleCacheManager.DebugAPI.ClearAllCache();
+ RefreshData();
+ }
+ }
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ private void DrawStatistics()
+ {
+ EditorGUILayout.BeginVertical(EditorStyles.helpBox);
+
+ EditorGUILayout.LabelField("缂撳瓨缁熻", EditorStyles.boldLabel);
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.LabelField($"Spine 璧勬簮鎬绘暟: {spineResourceViews.Count}", GUILayout.Width(200));
+ EditorGUILayout.LabelField($"Audio 璧勬簮鎬绘暟: {audioResourceViews.Count}", GUILayout.Width(200));
+ EditorGUILayout.LabelField($"鎴樺満鏁伴噺: {allBattleGuids.Count}", GUILayout.Width(200));
+ EditorGUILayout.EndHorizontal();
+
+ int spineLoaded = spineResourceViews.Count(v => v.IsLoaded);
+ int audioLoaded = audioResourceViews.Count(v => v.IsLoaded);
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.LabelField($"Spine 宸插姞杞�: {spineLoaded}", GUILayout.Width(200));
+ EditorGUILayout.LabelField($"Audio 宸插姞杞�: {audioLoaded}", GUILayout.Width(200));
+ EditorGUILayout.LabelField($"鎬诲紩鐢ㄨ鏁�: {spineResourceViews.Sum(v => v.TotalRefCount) + audioResourceViews.Sum(v => v.TotalRefCount)}", GUILayout.Width(200));
+ EditorGUILayout.EndHorizontal();
+
+ // 鎴樺満鍒楄〃
+ if (allBattleGuids.Count > 0)
+ {
+ GUILayout.Space(5);
+ EditorGUILayout.LabelField("娲昏穬鎴樺満:", EditorStyles.boldLabel);
+ EditorGUILayout.BeginHorizontal();
+ foreach (var guid in allBattleGuids)
+ {
+ string displayGuid = string.IsNullOrEmpty(guid) ? "[涓绘垬鍦篯" : guid.Substring(0, Mathf.Min(8, guid.Length)) + "...";
+ EditorGUILayout.LabelField($"鈥� {displayGuid}", GUILayout.Width(150));
+ }
+ EditorGUILayout.EndHorizontal();
+ }
+
+ EditorGUILayout.EndVertical();
+ }
+
+ private void DrawResourceSection(string title, List<BattleCacheManager.ResourceReferenceView> resources)
+ {
+ EditorGUILayout.BeginVertical(EditorStyles.helpBox);
+
+ EditorGUILayout.LabelField(title, headerStyle);
+ GUILayout.Space(5);
+
+ // 琛ㄥご
+ EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
+ EditorGUILayout.LabelField("璧勬簮璺緞", EditorStyles.toolbarButton, GUILayout.Width(600));
+ EditorGUILayout.LabelField("鐘舵��", EditorStyles.toolbarButton, GUILayout.Width(60));
+ EditorGUILayout.LabelField("寮曠敤璁℃暟", EditorStyles.toolbarButton, GUILayout.Width(80));
+ EditorGUILayout.LabelField("鎴樺満鍒嗗竷", EditorStyles.toolbarButton, GUILayout.ExpandWidth(true));
+ EditorGUILayout.EndHorizontal();
+
+ // 绛涢�夎祫婧�
+ var filteredResources = resources;
+ if (!string.IsNullOrEmpty(filterText))
+ {
+ filteredResources = resources.Where(r => r.ResourcePath.ToLower().Contains(filterText.ToLower())).ToList();
+ }
+
+ // 鍒涘缓灞呬腑鏍峰紡
+ GUIStyle centeredStyle = new GUIStyle(GUI.skin.label);
+ centeredStyle.alignment = TextAnchor.MiddleCenter;
+
+ GUIStyle centeredLoadedStyle = new GUIStyle(loadedStyle);
+ centeredLoadedStyle.alignment = TextAnchor.MiddleCenter;
+
+ GUIStyle centeredUnloadedStyle = new GUIStyle(unloadedStyle);
+ centeredUnloadedStyle.alignment = TextAnchor.MiddleCenter;
+
+ // 璧勬簮璺緞鏍峰紡锛堝彲鐐瑰嚮锛�
+ GUIStyle pathStyle = new GUIStyle(GUI.skin.label);
+ pathStyle.wordWrap = false;
+ pathStyle.normal.textColor = new Color(0.4f, 0.7f, 1f); // 娣¤摑鑹茶〃绀哄彲鐐瑰嚮
+
+ // 璧勬簮琛�
+ for (int i = 0; i < filteredResources.Count; i++)
+ {
+ var resource = filteredResources[i];
+ var rowStyle = (i % 2 == 0) ? evenRowStyle : oddRowStyle;
+
+ EditorGUILayout.BeginHorizontal(rowStyle);
+
+ // 璧勬簮璺緞锛堝彲鐐瑰嚮锛屾坊鍔� Tooltip锛�
+ GUIContent pathContent = new GUIContent(resource.ResourcePath, "鐐瑰嚮閫変腑璧勬簮\n" + resource.ResourcePath);
+ Rect pathRect = GUILayoutUtility.GetRect(pathContent, pathStyle, GUILayout.Width(600));
+
+ if (GUI.Button(pathRect, pathContent, pathStyle))
+ {
+ // 鐐瑰嚮鏃堕�変腑璧勬簮
+ SelectAssetInEditor(resource.ResourcePath);
+ }
+
+ // 榧犳爣鎮仠鏃舵樉绀烘墜鍨嬪厜鏍�
+ EditorGUIUtility.AddCursorRect(pathRect, MouseCursor.Link);
+
+ // 鍔犺浇鐘舵�侊紙灞呬腑锛�
+ var statusStyle = resource.IsLoaded ? centeredLoadedStyle : centeredUnloadedStyle;
+ EditorGUILayout.LabelField(resource.IsLoaded ? "宸插姞杞�" : "鏈姞杞�", statusStyle, GUILayout.Width(60));
+
+ // 寮曠敤璁℃暟锛堝眳涓級
+ EditorGUILayout.LabelField(resource.TotalRefCount.ToString(), centeredStyle, GUILayout.Width(80));
+
+ // 鎴樺満鍒嗗竷
+ string battleInfo = string.Join(", ", resource.BattlefieldRefCounts.Select(kvp =>
+ {
+ string guidDisplay = string.IsNullOrEmpty(kvp.Key) ? "[涓籡" : kvp.Key.Substring(0, Mathf.Min(4, kvp.Key.Length));
+ return $"{guidDisplay}({kvp.Value})";
+ }));
+ EditorGUILayout.LabelField(battleInfo, GUILayout.ExpandWidth(true));
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ if (filteredResources.Count == 0)
+ {
+ EditorGUILayout.LabelField("娌℃湁璧勬簮鏁版嵁", EditorStyles.centeredGreyMiniLabel);
+ }
+
+ EditorGUILayout.EndVertical();
+ }
+
+ private void RefreshData()
+ {
+ spineResourceViews.Clear();
+ audioResourceViews.Clear();
+ allBattleGuids.Clear();
+
+ // 鑾峰彇Spine璧勬簮
+ var spineCache = BattleCacheManager.DebugAPI.GetSpineCache();
+ foreach (var kvp in spineCache)
+ {
+ spineResourceViews.Add(new BattleCacheManager.ResourceReferenceView(kvp.Key, kvp.Value));
+ }
+
+ // 鑾峰彇Audio璧勬簮
+ var audioCache = BattleCacheManager.DebugAPI.GetAudioCache();
+ foreach (var kvp in audioCache)
+ {
+ audioResourceViews.Add(new BattleCacheManager.ResourceReferenceView(kvp.Key, kvp.Value));
+ }
+
+ // 鑾峰彇鎵�鏈夋垬鍦篏UID
+ allBattleGuids = BattleCacheManager.DebugAPI.GetAllBattleGuids();
+
+ // 鎺掑簭
+ spineResourceViews = spineResourceViews.OrderBy(v => v.ResourcePath).ToList();
+ audioResourceViews = audioResourceViews.OrderBy(v => v.ResourcePath).ToList();
+ }
+
+ /// <summary>
+ /// 鍦ㄧ紪杈戝櫒涓�変腑璧勬簮
+ /// </summary>
+ private void SelectAssetInEditor(string resourcePath)
+ {
+ // resourcePath 鏍煎紡: directory/assetName (渚嬪: Battle/Audio/bgm_001)
+ // 闇�瑕佽浆鎹负: Assets/ResourcesOut/{directory}/{assetName}{extension}
+
+ // 灏濊瘯澶氱鍙兘鐨勬墿灞曞悕
+ string[] possibleExtensions = new string[]
+ {
+ ".asset", // SkeletonDataAsset
+ ".prefab", // Prefabs
+ ".png", // Textures
+ ".jpg", // Textures
+ ".wav", // Audio
+ ".mp3", // Audio
+ ".ogg", // Audio
+ ".bytes", // Binary data
+ "", // 鏃犳墿灞曞悕
+ };
+
+ Object asset = null;
+ string foundPath = null;
+
+ // 灏濊瘯鎵�鏈夊彲鑳界殑璺緞
+ foreach (var ext in possibleExtensions)
+ {
+ string fullPath = $"Assets/ResourcesOut/{resourcePath}{ext}";
+ asset = AssetDatabase.LoadAssetAtPath<Object>(fullPath);
+ if (asset != null)
+ {
+ foundPath = fullPath;
+ break;
+ }
+ }
+
+ if (asset != null)
+ {
+ // 鍦� Project 绐楀彛涓�変腑骞堕珮浜�
+ Selection.activeObject = asset;
+ EditorGUIUtility.PingObject(asset);
+ Debug.Log($"宸查�変腑璧勬簮: {foundPath}");
+ }
+ else
+ {
+ // 濡傛灉鎵句笉鍒拌祫婧愶紝灏濊瘯浣跨敤 AssetDatabase.FindAssets 杩涜妯$硦鎼滅储
+ string assetName = System.IO.Path.GetFileName(resourcePath);
+ string[] guids = AssetDatabase.FindAssets(assetName);
+
+ if (guids != null && guids.Length > 0)
+ {
+ // 鎵惧埌鍖归厤鐨勮祫婧愶紝浼樺厛閫夋嫨璺緞鏈�鍖归厤鐨�
+ string bestMatch = null;
+ foreach (var guid in guids)
+ {
+ string assetPath = AssetDatabase.GUIDToAssetPath(guid);
+ if (assetPath.Contains(resourcePath))
+ {
+ bestMatch = assetPath;
+ break;
+ }
+ }
+
+ // 濡傛灉娌℃湁瀹屽叏鍖归厤锛屼娇鐢ㄧ涓�涓粨鏋�
+ if (bestMatch == null)
+ {
+ bestMatch = AssetDatabase.GUIDToAssetPath(guids[0]);
+ }
+
+ asset = AssetDatabase.LoadAssetAtPath<Object>(bestMatch);
+ if (asset != null)
+ {
+ Selection.activeObject = asset;
+ EditorGUIUtility.PingObject(asset);
+ Debug.Log($"閫氳繃鎼滅储鎵惧埌璧勬簮: {bestMatch}\n(鍘熷璺緞: {resourcePath})");
+ return;
+ }
+ }
+
+ Debug.LogWarning($"鏈壘鍒拌祫婧�: {resourcePath}\n灏濊瘯鐨勫熀纭�璺緞: Assets/ResourcesOut/{resourcePath}[extensions]");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta b/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta
new file mode 100644
index 0000000..298b3ad
--- /dev/null
+++ b/Assets/Editor/Tool/BattlePreloadResWatcher.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c91f4ead846c5154db3aa7ed7b93eb8a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
--
Gitblit v1.8.0