Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using System.IO;
- using System.Collections.Generic;
- using System.Text;
- using Newtonsoft.Json;
- using System.Linq;
- public class HierarchyTextLogger : EditorWindow
- {
- private bool logTransform = true;
- private bool logRigidbody = true;
- private bool logAsJson = true;
- private bool includeAllScripts = false;
- private bool includeOnlyEditorScripts = false;
- private bool includeAllProperties = false;
- private string customOutputPath = "Assets/HierarchyLog";
- private bool includeSpecificComponents = false;
- private string specificComponents = "";
- private bool logSpecificLayers = false;
- private string specificLayers = "";
- private bool logSpecificTags = false;
- private string specificTags = "";
- [MenuItem("Tools/Hierarchy Text Logger")]
- public static void ShowWindow()
- {
- GetWindow<HierarchyTextLogger>("Hierarchy Logger");
- }
- void OnGUI()
- {
- GUILayout.Label("Select Components to Log:", EditorStyles.boldLabel);
- logTransform = EditorGUILayout.Toggle("Log Transform", logTransform);
- logRigidbody = EditorGUILayout.Toggle("Log Rigidbody", logRigidbody);
- logAsJson = EditorGUILayout.Toggle("Output as JSON", logAsJson);
- includeAllScripts = EditorGUILayout.Toggle("Include All Scripts", includeAllScripts);
- if (includeAllScripts)
- includeOnlyEditorScripts = false;
- includeOnlyEditorScripts = EditorGUILayout.Toggle("Include Only Editor Scripts", includeOnlyEditorScripts);
- if (includeOnlyEditorScripts)
- includeAllScripts = false;
- includeAllProperties = EditorGUILayout.Toggle("Include All Properties", includeAllProperties);
- GUILayout.Space(10);
- customOutputPath = EditorGUILayout.TextField("Output Path", customOutputPath);
- includeSpecificComponents = EditorGUILayout.Toggle("Log Specific Components", includeSpecificComponents);
- if (includeSpecificComponents)
- {
- specificComponents = EditorGUILayout.TextField("Component Types (comma separated)", specificComponents);
- }
- logSpecificLayers = EditorGUILayout.Toggle("Log Specific Layers", logSpecificLayers);
- if (logSpecificLayers)
- {
- specificLayers = EditorGUILayout.TextField("Layer Names (comma separated)", specificLayers);
- }
- logSpecificTags = EditorGUILayout.Toggle("Log Specific Tags", logSpecificTags);
- if (logSpecificTags)
- {
- specificTags = EditorGUILayout.TextField("Tag Names (comma separated)", specificTags);
- }
- GUILayout.Space(10);
- if (GUILayout.Button("Log Hierarchy"))
- {
- LogHierarchy();
- }
- GUILayout.Space(10);
- if (GUILayout.Button("Import Hierarchy from JSON"))
- {
- ImportHierarchyFromJson();
- }
- }
- private void LogHierarchy()
- {
- var allObjects = new List<object>();
- StringBuilder builder = new StringBuilder();
- foreach (GameObject obj in SceneManager.GetActiveScene().GetRootGameObjects())
- {
- var objectData = LogObjectHierarchy(obj, builder, 0);
- if (logAsJson)
- allObjects.Add(objectData);
- else
- builder.AppendLine("");
- }
- string filePath = logAsJson ? $"{customOutputPath}.json" : $"{customOutputPath}.txt";
- File.WriteAllText(filePath, logAsJson ? Newtonsoft.Json.JsonConvert.SerializeObject(allObjects, Newtonsoft.Json.Formatting.Indented) : builder.ToString());
- AssetDatabase.Refresh();
- }
- private Dictionary<string, object> LogObjectHierarchy(GameObject obj, StringBuilder builder, int depth)
- {
- Dictionary<string, object> objectData = new Dictionary<string, object>();
- string indent = new string(' ', depth * 2);
- if (logSpecificLayers && !specificLayers.Split(',').Select(s => s.Trim()).Contains(LayerMask.LayerToName(obj.layer)))
- return null;
- if (logSpecificTags && !specificTags.Split(',').Select(s => s.Trim()).Contains(obj.tag))
- return null;
- builder.AppendLine($"{indent}GameObject: {obj.name}");
- objectData["Name"] = obj.name;
- objectData["Components"] = new List<object>();
- foreach (Component component in obj.GetComponents<Component>())
- {
- if (includeSpecificComponents && !specificComponents.Split(',').Select(s => s.Trim()).Contains(component.GetType().Name))
- continue;
- if (includeAllScripts && component is MonoBehaviour)
- {
- MonoBehaviour mono = component as MonoBehaviour;
- var script = MonoScript.FromMonoBehaviour(mono);
- var path = AssetDatabase.GetAssetPath(script);
- if (!string.IsNullOrEmpty(path))
- {
- string scriptContent = File.ReadAllText(path);
- Dictionary<string, string> scriptData = new Dictionary<string, string>
- {
- ["Name"] = mono.GetType().Name,
- ["Content"] = scriptContent
- };
- ((List<object>)objectData["Components"]).Add(scriptData);
- }
- }
- SerializedObject serializedObject = new SerializedObject(component);
- SerializedProperty prop = serializedObject.GetIterator();
- if (prop.NextVisible(true))
- {
- var componentData = new Dictionary<string, string>
- {
- ["Type"] = component.GetType().AssemblyQualifiedName
- };
- do
- {
- if (!includeAllProperties && !((component is Transform && logTransform) || (component is Rigidbody && logRigidbody)))
- continue;
- string value = GetPropertyValue(prop);
- componentData[prop.displayName] = value;
- builder.AppendLine($"{indent} {prop.displayName}: {value}");
- } while (prop.NextVisible(false));
- ((List<object>)objectData["Components"]).Add(componentData);
- }
- }
- objectData["Children"] = new List<object>();
- foreach (Transform child in obj.transform)
- {
- var childData = LogObjectHierarchy(child.gameObject, builder, depth + 1);
- if (childData != null)
- ((List<object>)objectData["Children"]).Add(childData);
- }
- return objectData;
- }
- private string GetPropertyValue(SerializedProperty prop)
- {
- try
- {
- switch (prop.propertyType)
- {
- case SerializedPropertyType.LayerMask:
- if (prop.intValue < 0 || prop.intValue >= UnityEngine.LayerMask.NameToLayer("UserLayerB") + 1)
- return "Invalid layer";
- return LayerMask.LayerToName(prop.intValue);
- case SerializedPropertyType.Integer:
- return prop.intValue.ToString();
- case SerializedPropertyType.Boolean:
- return prop.boolValue.ToString();
- case SerializedPropertyType.Float:
- return prop.floatValue.ToString("R");
- case SerializedPropertyType.String:
- return prop.stringValue;
- case SerializedPropertyType.Color:
- return prop.colorValue.ToString();
- case SerializedPropertyType.ObjectReference:
- return prop.objectReferenceValue != null ? prop.objectReferenceValue.name : "None";
- case SerializedPropertyType.Enum:
- return prop.enumNames[prop.enumValueIndex];
- case SerializedPropertyType.Vector2:
- return prop.vector2Value.ToString();
- case SerializedPropertyType.Vector3:
- return prop.vector3Value.ToString();
- case SerializedPropertyType.Vector4:
- return prop.vector4Value.ToString();
- case SerializedPropertyType.Rect:
- return prop.rectValue.ToString();
- case SerializedPropertyType.ArraySize:
- return prop.arraySize.ToString();
- case SerializedPropertyType.AnimationCurve:
- return prop.animationCurveValue != null ? prop.animationCurveValue.ToString() : "None";
- case SerializedPropertyType.Bounds:
- return prop.boundsValue.ToString();
- case SerializedPropertyType.Gradient:
- return "<Gradient unsupported>";
- case SerializedPropertyType.Quaternion:
- return prop.quaternionValue.ToString();
- case SerializedPropertyType.ExposedReference:
- return prop.exposedReferenceValue != null ? prop.exposedReferenceValue.ToString() : "None";
- case SerializedPropertyType.FixedBufferSize:
- return prop.fixedBufferSize.ToString();
- case SerializedPropertyType.Vector2Int:
- return prop.vector2IntValue.ToString();
- case SerializedPropertyType.Vector3Int:
- return prop.vector3IntValue.ToString();
- case SerializedPropertyType.RectInt:
- return prop.rectIntValue.ToString();
- case SerializedPropertyType.BoundsInt:
- return prop.boundsIntValue.ToString();
- default:
- return "<Unsupported Type>";
- }
- }
- catch (System.Exception ex)
- {
- return $"Error: {ex.Message}";
- }
- }
- void OnEnable()
- {
- includeAllScripts = EditorPrefs.GetBool("IncludeAllScripts", false);
- includeOnlyEditorScripts = EditorPrefs.GetBool("IncludeOnlyEditorScripts", false);
- includeAllProperties = EditorPrefs.GetBool("IncludeAllProperties", false);
- customOutputPath = EditorPrefs.GetString("CustomOutputPath", "Assets/HierarchyLog");
- includeSpecificComponents = EditorPrefs.GetBool("IncludeSpecificComponents", false);
- specificComponents = EditorPrefs.GetString("SpecificComponents", "");
- logSpecificLayers = EditorPrefs.GetBool("LogSpecificLayers", false);
- specificLayers = EditorPrefs.GetString("SpecificLayers", "");
- logSpecificTags = EditorPrefs.GetBool("LogSpecificTags", false);
- specificTags = EditorPrefs.GetString("SpecificTags", "");
- }
- void OnDisable()
- {
- EditorPrefs.SetBool("IncludeAllScripts", includeAllScripts);
- EditorPrefs.SetBool("IncludeOnlyEditorScripts", includeOnlyEditorScripts);
- EditorPrefs.SetBool("IncludeAllProperties", includeAllProperties);
- EditorPrefs.SetString("CustomOutputPath", customOutputPath);
- EditorPrefs.SetBool("IncludeSpecificComponents", includeSpecificComponents);
- EditorPrefs.SetString("SpecificComponents", specificComponents);
- EditorPrefs.SetBool("LogSpecificLayers", logSpecificLayers);
- EditorPrefs.SetString("SpecificLayers", specificLayers);
- EditorPrefs.SetBool("LogSpecificTags", logSpecificTags);
- EditorPrefs.SetString("SpecificTags", specificTags);
- }
- private void ImportHierarchyFromJson()
- {
- string importPath = $"{customOutputPath}.json";
- if (!File.Exists(importPath))
- {
- Debug.LogError("JSON file not found at the specified path.");
- return;
- }
- string jsonContent = File.ReadAllText(importPath);
- var rootObjectData = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(jsonContent);
- if (rootObjectData != null)
- {
- foreach (var objectData in rootObjectData)
- {
- CreateGameObjectFromJson(objectData, null);
- }
- }
- AssetDatabase.Refresh();
- }
- private void CreateGameObjectFromJson(Dictionary<string, object> objectData, Transform parent)
- {
- if (!objectData.ContainsKey("Name"))
- {
- Debug.LogError("Object data does not contain 'Name' key.");
- return;
- }
- string name = objectData["Name"].ToString();
- GameObject newObject = new GameObject(name);
- Debug.Log($"Created GameObject: {name}");
- if (parent != null)
- {
- newObject.transform.SetParent(parent);
- }
- if (objectData.ContainsKey("Components"))
- {
- var components = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(objectData["Components"].ToString());
- foreach (var componentData in components)
- {
- if (componentData != null && componentData.ContainsKey("Type"))
- {
- string componentName = componentData["Type"].ToString();
- Component component = newObject.AddComponent(System.Type.GetType(componentName));
- Debug.Log($"Added Component: {componentName} to {name}");
- if (component != null)
- {
- SerializedObject serializedObject = new SerializedObject(component);
- foreach (var prop in componentData)
- {
- if (prop.Key == "Type")
- continue;
- SerializedProperty serializedProperty = serializedObject.FindProperty(prop.Key);
- if (serializedProperty != null)
- {
- SetPropertyValue(serializedProperty, prop.Value.ToString());
- }
- else
- {
- Debug.LogWarning($"Property '{prop.Key}' not found in component '{componentName}'");
- }
- }
- serializedObject.ApplyModifiedProperties();
- }
- else
- {
- Debug.LogError($"Failed to add component '{componentName}' to GameObject '{name}'");
- }
- }
- }
- }
- else
- {
- Debug.LogError($"Object '{name}' does not contain 'Components' key or 'Components' is not a list.");
- }
- if (objectData.ContainsKey("Children"))
- {
- var children = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(objectData["Children"].ToString());
- foreach (var childData in children)
- {
- if (childData != null)
- {
- CreateGameObjectFromJson(childData, newObject.transform);
- }
- }
- }
- }
- private void SetPropertyValue(SerializedProperty prop, string value)
- {
- try
- {
- switch (prop.propertyType)
- {
- case SerializedPropertyType.Integer:
- prop.intValue = int.Parse(value);
- break;
- case SerializedPropertyType.Boolean:
- prop.boolValue = bool.Parse(value);
- break;
- case SerializedPropertyType.Float:
- prop.floatValue = float.Parse(value);
- break;
- case SerializedPropertyType.String:
- prop.stringValue = value;
- break;
- case SerializedPropertyType.Color:
- prop.colorValue = ColorUtility.TryParseHtmlString(value, out Color color) ? color : Color.white;
- break;
- case SerializedPropertyType.ObjectReference:
- // This is a simplification. Ideally, you'd resolve the reference properly.
- prop.objectReferenceValue = null;
- break;
- case SerializedPropertyType.Enum:
- prop.enumValueIndex = prop.enumNames.ToList().IndexOf(value);
- break;
- case SerializedPropertyType.Vector2:
- prop.vector2Value = JsonConvert.DeserializeObject<Vector2>(value);
- break;
- case SerializedPropertyType.Vector3:
- prop.vector3Value = JsonConvert.DeserializeObject<Vector3>(value);
- break;
- case SerializedPropertyType.Vector4:
- prop.vector4Value = JsonConvert.DeserializeObject<Vector4>(value);
- break;
- case SerializedPropertyType.Rect:
- prop.rectValue = JsonConvert.DeserializeObject<Rect>(value);
- break;
- case SerializedPropertyType.Bounds:
- prop.boundsValue = JsonConvert.DeserializeObject<Bounds>(value);
- break;
- case SerializedPropertyType.Quaternion:
- prop.quaternionValue = JsonConvert.DeserializeObject<Quaternion>(value);
- break;
- case SerializedPropertyType.Vector2Int:
- prop.vector2IntValue = JsonConvert.DeserializeObject<Vector2Int>(value);
- break;
- case SerializedPropertyType.Vector3Int:
- prop.vector3IntValue = JsonConvert.DeserializeObject<Vector3Int>(value);
- break;
- case SerializedPropertyType.RectInt:
- prop.rectIntValue = JsonConvert.DeserializeObject<RectInt>(value);
- break;
- case SerializedPropertyType.BoundsInt:
- prop.boundsIntValue = JsonConvert.DeserializeObject<BoundsInt>(value);
- break;
- default:
- Debug.LogWarning($"Unsupported property type: {prop.propertyType}");
- break;
- }
- }
- catch (System.Exception ex)
- {
- Debug.LogError($"Failed to set property value: {ex.Message}");
- }
- }
- }
Add Comment
Please, Sign In to add comment