using System; using System.Collections.Generic; using System.IO; using System.Text; using UIInfoBuilder.ComponentExtractors; using UIInfoBuilder.Data; using UnityEditor; using UnityEngine; namespace UIInfoBuilder { public class UIInfoExtractor { private static readonly List _extractors = new List(); private static readonly DefaultComponentExtractor _defaultExtractor = new DefaultComponentExtractor(); static UIInfoExtractor() { // 注册特殊组件提取器(优先级高的放前面) _extractors.Add(new RectTransformExtractor()); _extractors.Add(new ImageExtractor()); _extractors.Add(new TextExtractor()); _extractors.Add(new ButtonExtractor()); } [MenuItem("Assets/UIInfoBuilder/ExtractPrefab")] private static void _AssetHandle() { var selectedObjects = Selection.gameObjects; foreach (var obj in selectedObjects) { string savePath = Application.dataPath + "/../ExtractedPrefabs/" + obj.name + ".json"; ExtractPrefab(obj, savePath); Debug.Log($"[UIInfoBuilder] Extracted: {obj.name} -> {savePath}"); } } /// /// 提取 Prefab 信息并保存为 JSON /// public static void ExtractPrefab(GameObject prefab, string savePath) { var rootNode = _ExtractNode(prefab); _SaveToJson(rootNode, savePath); } /// /// 递归提取节点信息 /// private static UIInfoNode _ExtractNode(GameObject go) { var node = new UIInfoNode { name = go.name, active = go.activeSelf }; // 提取所有组件 var components = go.GetComponents(); foreach (var component in components) { if (component == null) continue; var compInfo = _ExtractComponent(component); node.components.Add(compInfo); } // 递归提取子节点 for (int i = 0; i < go.transform.childCount; i++) { var child = go.transform.GetChild(i).gameObject; var childNode = _ExtractNode(child); node.children.Add(childNode); } return node; } /// /// 提取单个组件信息 /// private static UIInfoComponent _ExtractComponent(Component component) { var info = new UIInfoComponent { componentName = component.GetType().Name, enable = _GetComponentEnabled(component) }; // 查找匹配的特殊提取器 IComponentExtractor extractor = null; foreach (var ext in _extractors) { if (ext.CanExtract(component)) { extractor = ext; break; } } // 使用特殊提取器或默认提取器 if (extractor != null) { extractor.Extract(component, info); } else { _defaultExtractor.Extract(component, info); } return info; } /// /// 获取组件的启用状态 /// private static bool _GetComponentEnabled(Component component) { // Behaviour 类型的组件有 enabled 属性 if (component is Behaviour behaviour) { return behaviour.enabled; } // Renderer 类型的组件有 enabled 属性 if (component is Renderer renderer) { return renderer.enabled; } // Collider 类型的组件有 enabled 属性 if (component is Collider collider) { return collider.enabled; } // 其他组件默认返回 true return true; } /// /// 保存为 JSON 文件 /// private static void _SaveToJson(UIInfoNode node, string savePath) { // 确保目录存在 string directory = Path.GetDirectoryName(savePath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } // 使用自定义递归序列化(JsonUtility 不支持嵌套 List 递归) var sb = new StringBuilder(); _SerializeNode(node, sb, 0); File.WriteAllText(savePath, sb.ToString()); } /// /// 递归序列化节点为 JSON /// private static void _SerializeNode(UIInfoNode node, StringBuilder sb, int indent) { string indentStr = new string(' ', indent * 2); string indentStr1 = new string(' ', (indent + 1) * 2); string indentStr2 = new string(' ', (indent + 2) * 2); string indentStr3 = new string(' ', (indent + 3) * 2); sb.AppendLine($"{indentStr}{{"); sb.AppendLine($"{indentStr1}\"name\": \"{_EscapeJsonString(node.name)}\","); sb.AppendLine($"{indentStr1}\"active\": {node.active.ToString().ToLower()},"); // Components sb.AppendLine($"{indentStr1}\"components\": ["); for (int i = 0; i < node.components.Count; i++) { var comp = node.components[i]; sb.AppendLine($"{indentStr2}{{"); sb.AppendLine($"{indentStr3}\"componentName\": \"{_EscapeJsonString(comp.componentName)}\","); sb.AppendLine($"{indentStr3}\"enable\": {comp.enable.ToString().ToLower()},"); sb.Append($"{indentStr3}\"properties\": ["); if (comp.properties.Count > 0) { sb.AppendLine(); for (int j = 0; j < comp.properties.Count; j++) { string comma = j < comp.properties.Count - 1 ? "," : ""; sb.AppendLine($"{indentStr3} \"{_EscapeJsonString(comp.properties[j])}\"{comma}"); } sb.AppendLine($"{indentStr3}]"); } else { sb.AppendLine("]"); } string compComma = i < node.components.Count - 1 ? "," : ""; sb.AppendLine($"{indentStr2}}}{compComma}"); } sb.AppendLine($"{indentStr1}],"); // Children sb.AppendLine($"{indentStr1}\"children\": ["); for (int i = 0; i < node.children.Count; i++) { _SerializeNode(node.children[i], sb, indent + 2); if (i < node.children.Count - 1) { // 在上一个 } 后面加逗号 sb.Length -= Environment.NewLine.Length; // 移除换行 sb.AppendLine(","); } } sb.AppendLine($"{indentStr1}]"); sb.AppendLine($"{indentStr}}}"); } /// /// 转义 JSON 字符串中的特殊字符 /// private static string _EscapeJsonString(string str) { if (string.IsNullOrEmpty(str)) return str; return str .Replace("\\", "\\\\") .Replace("\"", "\\\"") .Replace("\n", "\\n") .Replace("\r", "\\r") .Replace("\t", "\\t"); } } }