├── Editor └── SerializedPropertyViewer.cs ├── README.md └── sp_viewer.png /Editor/SerializedPropertyViewer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Text; 4 | using System.Reflection; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | public class SerializedPropertyViewer : EditorWindow 9 | { 10 | 11 | public class SPData 12 | { 13 | public int depth; 14 | public string info; 15 | public string val; 16 | public int oid; 17 | 18 | public SPData(int d, string i, string v, int o) 19 | { 20 | if(d < 0) 21 | { 22 | d = 0; 23 | } 24 | depth = d; 25 | info = i; 26 | val = v; 27 | oid = o; 28 | } 29 | } 30 | 31 | [MenuItem ("Window/SP Viewer")] 32 | static void Init () 33 | { 34 | // Get existing open window or if none, make a new one: 35 | SerializedPropertyViewer window = (SerializedPropertyViewer)EditorWindow.GetWindow (typeof (SerializedPropertyViewer)); 36 | window.titleContent = new GUIContent("SP Viewer"); 37 | window.Show(); 38 | } 39 | 40 | UnityEngine.Object obj; 41 | 42 | Vector2 scrollPos; 43 | List data; 44 | bool dirty = true; 45 | string searchStr = ""; 46 | string searchStrRep; 47 | 48 | bool debugMode; 49 | public static GUIStyle richTextStyle; 50 | 51 | 52 | void OnGUI () 53 | { 54 | if(richTextStyle == null) 55 | { 56 | //EditorStyles does not exist in Constructor?? 57 | richTextStyle = new GUIStyle(EditorStyles.label); 58 | richTextStyle.richText = true; 59 | } 60 | 61 | UnityEngine.Object newObj = EditorGUILayout.ObjectField("Object:", obj, typeof(UnityEngine.Object), true); 62 | debugMode = EditorGUILayout.Toggle("Debug Mode", debugMode); 63 | if((GUILayout.Button("Refresh"))) 64 | { 65 | obj = null; 66 | } 67 | 68 | string newSearchStr = EditorGUILayout.TextField("Search:", searchStr); 69 | if(newSearchStr != searchStr) 70 | { 71 | searchStr = newSearchStr; 72 | searchStrRep = ""+searchStr+""; 73 | dirty = true; 74 | } 75 | if(obj != newObj) 76 | { 77 | obj = newObj; 78 | dirty = true; 79 | } 80 | if(data == null) 81 | { 82 | dirty = true; 83 | } 84 | if(dirty == true) 85 | { 86 | dirty = false; 87 | searchObject(obj); 88 | } 89 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos); 90 | foreach(SPData line in data) 91 | { 92 | EditorGUI.indentLevel = line.depth; 93 | if(line.oid > 0){ 94 | GUILayout.BeginHorizontal(); 95 | 96 | } 97 | EditorGUILayout.SelectableLabel(line.info, richTextStyle, GUILayout.Height(20)); 98 | if(line.oid > 0) 99 | { 100 | if(GUILayout.Button(">>", GUILayout.Width(50))) 101 | { 102 | Selection.activeInstanceID = line.oid; 103 | } 104 | 105 | GUILayout.EndHorizontal(); 106 | } 107 | } 108 | EditorGUILayout.EndScrollView(); 109 | 110 | if(GUILayout.Button("Copy To Clipboard")) 111 | { 112 | StringBuilder sb = new StringBuilder(); 113 | Dictionary paddingHash = new Dictionary(); 114 | string padding = ""; 115 | for(int i = 0; i < 40; i++) 116 | { 117 | paddingHash[i] = padding; 118 | padding += " "; 119 | } 120 | foreach(SPData line in data) 121 | { 122 | sb.Append(paddingHash[line.depth]); 123 | sb.Append(line.info); 124 | sb.Append("\n"); 125 | } 126 | EditorGUIUtility.systemCopyBuffer = sb.ToString(); 127 | } 128 | } 129 | 130 | void searchObject(UnityEngine.Object obj) 131 | { 132 | data = new List(); 133 | if(obj == null) 134 | { 135 | return; 136 | } 137 | SerializedObject so = new SerializedObject(obj); 138 | if(debugMode) 139 | { 140 | PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance); 141 | inspectorModeInfo.SetValue(so, InspectorMode.Debug, null); 142 | } 143 | 144 | SerializedProperty iterator = so.GetIterator(); 145 | search(iterator, 0); 146 | } 147 | 148 | void search(SerializedProperty prop, int depth) 149 | { 150 | logProperty(prop); 151 | while(prop.Next(true)) 152 | { 153 | logProperty(prop); 154 | } 155 | } 156 | 157 | 158 | void logProperty(SerializedProperty prop) 159 | { 160 | string strVal = getStringValue(prop); 161 | string propDesc = prop.propertyPath+" type:"+prop.type + " name:"+prop.name + " val:"+ strVal + " isArray:"+prop.isArray; 162 | if(searchStr.Length > 0) 163 | { 164 | propDesc = propDesc.Replace(searchStr, searchStrRep); 165 | } 166 | data.Add(new SPData(prop.depth, propDesc, strVal, getObjectID(prop))); 167 | } 168 | 169 | int getObjectID(SerializedProperty prop) 170 | { 171 | if(prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue != null) 172 | { 173 | return prop.objectReferenceValue.GetInstanceID(); 174 | } 175 | return 0; 176 | } 177 | 178 | string getStringValue(SerializedProperty prop) 179 | { 180 | switch(prop.propertyType) 181 | { 182 | case SerializedPropertyType.String: 183 | return prop.stringValue; 184 | case SerializedPropertyType.Character: //this isn't really a thing, chars are ints! 185 | case SerializedPropertyType.Integer: 186 | if(prop.type == "char") 187 | { 188 | return System.Convert.ToChar(prop.intValue).ToString(); 189 | } 190 | return prop.intValue.ToString(); 191 | case SerializedPropertyType.ObjectReference: 192 | if(prop.objectReferenceValue != null) 193 | { 194 | return prop.objectReferenceValue.ToString(); 195 | }else{ 196 | return "(null)"; 197 | } 198 | case SerializedPropertyType.Float: 199 | return prop.floatValue.ToString(); 200 | default: 201 | return ""; 202 | } 203 | } 204 | 205 | 206 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serialized Property Viewer 2 | 3 | This is a utility window for Unity3D that exposes the [SerializedProperties](http://docs.unity3d.com/ScriptReference/SerializedProperty.html) of an object. 4 | 5 | ## Why Would I Use This Thing? 6 | 7 | Have you ever needed to know exactly how Unity serializes your game object/behaviour/thing? Maybe you need to create an Editor in Unity but having trouble figuring out how the data is exposed? Maybe you want to see how Unity serializes its own internal objects? If you're doing something in the Editor, you need to see it how the Editor sees it. Which is NOT intuitive. Hence the SerializedPropertyViewer. 8 | 9 | ![](sp_viewer.png) 10 | 11 | Usage is quite straightforward: drag an object into the `Object` field and observe the output. This is unfiltered so expect lots of info. For example, char* are displayed as arrays, and object references are shown as a PPtr (which contains two values: m_FileID, and m_PathID). 12 | 13 | ## Features 14 | 15 | * Displays everything how Unity sees it. 16 | * 'Debug Mode' turns on the 'm_LocalIdentfierInFile' hack to get access to the m_InstanceID. 17 | * Search field that will highlight in green the string entered. 18 | * When an object is found a 'goto' button is displayed. 19 | * Displays the propertyPath, which you can use as input to [FindProperty()](http://docs.unity3d.com/ScriptReference/SerializedObject.FindProperty.html) 20 | 21 | [This is part of the Enemy Hideout Code Archive](http://enemyhideout.com/2016/05/free-code-from-the-hideout/) -------------------------------------------------------------------------------- /sp_viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotron2084/serializedpropertyviewer/a8d2fcfe76ca9c2b6d3f311adf9048be55755c16/sp_viewer.png --------------------------------------------------------------------------------