using System.Collections.Generic; using System.Runtime.Serialization; using System.Linq; using UnityEngine; using UnityEngine.AddressableAssets; using System.Reflection; using CommonSerializeDefine; using System.Text.RegularExpressions; #if UNITY_EDITOR using UnityEditor; using UnityEditor.Build; using UnityEditor.Build.Reporting; public class PreBuildScript : IPreprocessBuildWithReport { // The order in which the callback will be executed relative to other preprocess build callbacks. public int callbackOrder => 0; // This method will be called before the build starts. public void OnPreprocessBuild(BuildReport report) { PrefabChecker.CheckAndCreatePrefab(); } } [InitializeOnLoad] public static class PrefabChecker { static PrefabChecker() { // Subscribe to the event that's called after scripts are recompiled //EditorApplication.delayCall += CheckAndCreatePrefab; EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } private static void OnPlayModeStateChanged(PlayModeStateChange state) { // Check if the editor is about to enter Play mode if (state == PlayModeStateChange.ExitingEditMode) { CheckAndCreatePrefab(); } } public static void CheckAndCreatePrefab() { // Path to the folder containing the prefab string prefabPath = $"Assets/Resources/{ODUnityObjectMapper.MapperResourcePath}.prefab"; // Load the prefab GameObject prefab = AssetDatabase.LoadAssetAtPath(prefabPath); if (prefab == null) { Debug.LogWarning($"Prefab not found at path: {prefabPath}. Creating a new one."); // Create a new GameObject and add the ODUnitySerializer component GameObject newPrefab = new GameObject("ObjectMapper"); var comp = newPrefab.AddComponent(); try { GatherUnityObjects(comp); // Create the necessary directories if they don't exist string directoryPath = "Assets/Resources/ODUnityExtension/ObjectMapping"; if (!AssetDatabase.IsValidFolder(directoryPath)) { AssetDatabase.CreateFolder("Assets", "Resources"); AssetDatabase.CreateFolder("Assets/Resources", "ODUnityExtension"); AssetDatabase.CreateFolder("Assets/Resources/ODUnityExtension", "ObjectMapping"); } // Save the new GameObject as a prefab PrefabUtility.SaveAsPrefabAsset(newPrefab, prefabPath); Debug.Log($"New prefab created at path: {prefabPath}"); } finally { // Destroy the temporary GameObject MonoBehaviour.DestroyImmediate(prefab); Debug.Log($"{prefab} prefab destroyed"); } } else { // Check if the prefab has the ODUnitySerializer component if (prefab.GetComponent() == null) { Debug.LogWarning($"Prefab at path: {prefabPath} does not contain an ODUnitySerializer component. Adding the component."); // Add the component to the prefab var comp = prefab.AddComponent(); GatherUnityObjects(comp); EditorUtility.SetDirty(prefab); AssetDatabase.SaveAssets(); } else { GatherUnityObjects(prefab.GetComponent()); EditorUtility.SetDirty(prefab); AssetDatabase.SaveAssets(); Debug.Log("Prefab check passed. ODUnitySerializer component exists."); } } } private static void GatherUnityObjects(ODUnityObjectMapper mapper) { mapper.AllUnityObjects = new List(); mapper.AllUnityObjectGUIDs = new List(); foreach (var item in GetAllUnityObjects(mapper.WhiteListPath)) { mapper.AllUnityObjects.Add(item.Key); mapper.AllUnityObjectGUIDs.Add(item.Value); } } private static IEnumerable> GetAllUnityObjects(IEnumerable whileList = null) { string[] guids = AssetDatabase.FindAssets("t:ScriptableObject t:Prefab"); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (whileList != null && whileList.Count() != 0) { if (!whileList.Any(str => assetPath.StartsWith(str))) { continue; } } Object asset = AssetDatabase.LoadAssetAtPath(assetPath); if (asset is ScriptableObject scriptableObject) { yield return new KeyValuePair(asset, guid); } else if (asset is GameObject prefab) { yield return new KeyValuePair(asset, guid); } } } } #endif public class ODUnityPrefabSerializer { public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; GameObject prefab = obj as GameObject; string guid = mapper.GetObjectGUID(prefab); info.AddValue("guid", guid); } public IEnumerable GetSerializeTypes() { yield return typeof(GameObject); } public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; string guid = info.GetString("guid"); return mapper.GetObject(guid); } } public static class UnitySerializerUtils { public static string RemoveContentInParentheses(string input) { if (input == null) { return null; } if (input.Length == 0) { return input; } // Regular expression to match content inside parentheses including the parentheses string pattern = @"\([^)]*\)"; // Replace all matches with an empty string string result = Regex.Replace(input, pattern, string.Empty); // Return the cleaned-up string return result; } } public class GameObjectSerializer : CommonSerializeDefine.ITypeSerializer { public bool CanSerialize(System.Type type) { return type == typeof(GameObject); } public object Deserialize(string obj, System.Type type, IDeserializer deserializer) { obj = UnitySerializerUtils.RemoveContentInParentheses(obj); if (XHelper.StringUtils.IsEmpty(obj)) { return null; } ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; GameObject go = mapper.GetObject(obj) as GameObject; //return go.GetComponent(info.ObjectType); return go; } public string Serialize(object obj, System.Type type, ISerializer serializer) { GameObject go = obj as GameObject; ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; return $"({go.name}){mapper.GetObjectGUID(go)}"; } } public class ComponentSerializer : CommonSerializeDefine.ITypeSerializer { public bool CanSerialize(System.Type type) { return type.IsSubclassOf(typeof(MonoBehaviour)); } public object Deserialize(string obj, System.Type type, IDeserializer deserializer) { obj = UnitySerializerUtils.RemoveContentInParentheses(obj); if (XHelper.StringUtils.IsEmpty(obj)) { return null; } ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; GameObject go = mapper.GetObject(obj) as GameObject; return go.GetComponent(type); } public string Serialize(object obj, System.Type type, ISerializer serializer) { MonoBehaviour mono = (MonoBehaviour)obj; GameObject go = mono.gameObject; ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; return $"({go.name}.{type.Name}){mapper.GetObjectGUID(go)}"; } } public class ScriptableObjectSerializer : CommonSerializeDefine.ITypeSerializer { public bool CanSerialize(System.Type type) { return type.IsSubclassOf(typeof(ScriptableObject)); } public object Deserialize(string obj, System.Type type, IDeserializer deserializer) { obj = UnitySerializerUtils.RemoveContentInParentheses(obj); if (XHelper.StringUtils.IsEmpty(obj)) { return null; } ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; return mapper.GetObject(obj); } public string Serialize(object obj, System.Type type, ISerializer serializer) { ScriptableObject so = obj as ScriptableObject; ODUnityObjectMapper mapper = ODUnityObjectMapper.ObjectMapper; return $"({so.name}){mapper.GetObjectGUID(so)}"; } } public class AddressableSerializer : CommonSerializeDefine.ITypeSerializer { public bool CanSerialize(System.Type type) { if (type == typeof(AssetReference)) { return true; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(AssetReferenceT<>)) { return true; } return false; } public object Deserialize(string obj, System.Type type, IDeserializer deserializer) { obj = UnitySerializerUtils.RemoveContentInParentheses(obj); if (XHelper.StringUtils.IsEmpty(obj)) { return null; } string guid; string subObjectName; int index = obj.IndexOf(':'); if (index == -1) { guid = obj; subObjectName = ""; } else { guid = obj.Substring(0, index); subObjectName = obj.Substring(index + 1); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(AssetReferenceT<>)) { AssetReference asset = System.Activator.CreateInstance(type, guid) as AssetReference; asset.SubObjectName = subObjectName; return obj; } else { AssetReference asset = new AssetReference(guid); asset.SubObjectName = subObjectName; return asset; } } public string Serialize(object obj, System.Type type, ISerializer serializer) { throw new System.NotImplementedException(); } }