private static Object SerializeObject(object obj, Dictionary <object, Object> serialized, bool skipNoCopyAttribute = false, Action <object, Object> onAfterSerialize = null) ///If skipNotCopyAttribute will skip all fields marked with NoCopy attribute { //null if (obj == null) { return(Object.Null); } //if (obj is UnityEngine.Object && (UnityEngine.Object)obj == (UnityEngine.Object)null) // return Object.Null; //in some cases treats other graph as null. Better skip nulls on deserialize //already serialized if (serialized.TryGetValue(obj, out Object serObj)) { return(serObj); } //type ignored //if (obj is ) return Object.Null; serObj = new Object(); serialized.Add(obj, serObj); //adding before calling any other Serialize to prevent infinite loops serObj.refId = serialized.Count - 1; Type type = obj.GetType(); serObj.type = type.AssemblyQualifiedName; //string if (type == typeof(string)) { serObj.special = (string)obj; } //guid if (type == typeof(Guid)) { serObj.special = ((Guid)obj).ToString(); } //unity object //else if (type.IsSubclassOf(typeof(UnityEngine.Object)) && !type.IsSubclassOf(typeof(UnityEngine.ScriptableObject))) else if (type.IsSubclassOf(typeof(UnityEngine.Object))) { serObj.uniObj = (UnityEngine.Object)obj; } //serializer else if (type == typeof(Object[])) { throw new Exception("Serializer is trying to serialize serializer objects. This is causing infinite loop."); } //reflections else if (type.IsSubclassOf(typeof(MemberInfo))) { if (type.IsSubclassOf(typeof(Type))) //could be MonoType { serObj.special = ((Type)obj).AssemblyQualifiedName; } else { MemberInfo mi = (MemberInfo)obj; serObj.special = mi.Name + ", " + mi.DeclaringType.AssemblyQualifiedName; } } //primitives (if they were assigned to object field) else if (type.IsPrimitive) { serObj.values = new Value[1]; serObj.values[0].Set(obj, type); } //animation curve else if (type == typeof(AnimationCurve)) { AnimationCurve curve = (AnimationCurve)obj; serObj.values = new Value[3]; serObj.values[0] = SerializeObject(curve.keys, serialized, onAfterSerialize: onAfterSerialize).refId; serObj.values[1].Set((int)curve.preWrapMode, typeof(int)); serObj.values[2].Set((int)curve.postWrapMode, typeof(int)); } //array else if (type.IsArray) { Array array = (Array)obj; serObj.fields = null; serObj.values = new Value[array.Length]; Type elementType = type.GetElementType(); bool elementTypeIsPrimitive = elementType.IsPrimitive; for (int i = 0; i < array.Length; i++) { object val = array.GetValue(i); Value serVal = new Value(); if (elementTypeIsPrimitive) { serVal.Set(val, elementType); } else { serVal = SerializeObject(val, serialized, onAfterSerialize: onAfterSerialize).refId; } serObj.values[i] = serVal; } } //another more relable Unity Object null check else if (type == typeof(UnityEngine.Object)) { FieldInfo ptrField = type.GetField("m_CachedPtr", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); IntPtr ptr = (IntPtr)ptrField.GetValue(obj); if (ptr == IntPtr.Zero) { return(Object.Null); } } //class/struct else { if (obj is ISerializationCallbackReceiver) { ((ISerializationCallbackReceiver)obj).OnBeforeSerialize(); } if (obj is IAlternativeType altTypeObj) { serObj.altType = altTypeObj.AlternativeSerializationType.AssemblyQualifiedName; } FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //special cases when derive from list - adding base class values if (obj is IList || obj is IDictionary) { ArrayTools.Append(ref fields, type.BaseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)); } List <FieldInfo> usedFields = new List <FieldInfo>(); for (int f = 0; f < fields.Length; f++) { FieldInfo field = fields[f]; if (field.IsLiteral) { continue; //leaving constant fields blank } if (field.FieldType.IsPointer) { continue; //skipping pointers (they make unity crash. Maybe require unsafe) } if (field.IsNotSerialized) { continue; } if (skipNoCopyAttribute) { object[] noCopyAttributes = field.GetCustomAttributes(typeof(NoCopyAttribute), false); if (noCopyAttributes.Length != 0) { continue; //SOMEDAY: make NoCopy a serializer control attribute with values inside } } usedFields.Add(field); } int usedFieldsCount = usedFields.Count; serObj.fields = new string[usedFieldsCount]; serObj.values = new Value[usedFieldsCount]; for (int f = 0; f < usedFieldsCount; f++) { FieldInfo field = usedFields[f]; serObj.fields[f] = field.Name; object val = field.GetValue(obj); Value serVal = new Value(); if (field.FieldType.IsPrimitive) { serVal.Set(val, field.FieldType); } else { serVal = SerializeObject(val, serialized, onAfterSerialize: onAfterSerialize).refId; } serObj.values[f] = serVal; } if (obj is ICustomSerialization customObj) { customObj.PostprocessAfterSerialize(serObj, serialized); } } onAfterSerialize?.Invoke(obj, serObj); return(serObj); }
public static void SetUserData(this UnityEditor.AssetImporter importer, string param, string[] data, bool reload = false) { char endline = '\n'; //';' string userData = importer.userData; string[] userDataSplit = userData.Split('\n', ';'); //preparing new data line if (data == null) { data = new string[0]; } string newDataString = param + ":" + data.ToStringMemberwise(separator: ","); //param line number (-1 if not found) int numInSplit = -1; for (int i = 0; i < userDataSplit.Length; i++) { if (userDataSplit[i].StartsWith(param + ":")) { numInSplit = i; } } //erasing empty data if (numInSplit >= 0 && data.Length == 0) { ArrayTools.RemoveAt(ref userDataSplit, numInSplit); } //replacing line if (numInSplit >= 0 && data.Length != 0) { userDataSplit[numInSplit] = newDataString; } //adding new line if (numInSplit == -1 && data.Length != 0) { ArrayTools.Add(ref userDataSplit, newDataString); } //to string string newUserData = ""; for (int i = 0; i < userDataSplit.Length; i++) { if (userDataSplit[i].Length == 0) { continue; } newUserData += userDataSplit[i]; if (i != userDataSplit.Length - 1) { newUserData += endline; } } //writing if (newUserData != userData) { importer.userData = newUserData; UnityEditor.EditorUtility.SetDirty(importer); UnityEditor.AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath); if (reload) { UnityEditor.AssetDatabase.Refresh(); } } }