using System; using System.Linq; using System.Reflection; using UnityEngine; namespace BrewMonster { public static class ResetStaticUtility { private const string AutoRunOnPlayPrefsKey = "ResetStaticUtility.AutoRunOnPlay"; public static int ResetAll(bool logEach = false, Func assemblyFilter = null) { int resetCount = 0; var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { if (assembly.IsDynamic) { continue; } if (assemblyFilter == null) { string name = assembly.GetName().Name; if (!(name == "Assembly-CSharp" || name == "Assembly-CSharp-firstpass" || name.StartsWith("Assembly-CSharp-"))) { continue; } } else if (!assemblyFilter(assembly)) { continue; } Type[] types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types.Where(t => t != null).ToArray(); } catch (Exception ex) { Debug.LogWarning($"[ResetStatic] Failed to enumerate types for assembly {assembly.FullName}: {ex}"); continue; } foreach (var type in types) { if (type == null) { continue; } FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); foreach (var field in fields) { if (field.IsLiteral || field.IsInitOnly) { continue; } var attr = field.GetCustomAttribute(false); if (attr == null) { continue; } try { object newValue = null; object currentValue = field.GetValue(null); if (field.FieldType.IsValueType) { newValue = Activator.CreateInstance(field.FieldType); field.SetValue(null, newValue); resetCount++; if (logEach) { Debug.Log($"[ResetStatic] {type.FullName}.{field.Name} set to default({field.FieldType.Name})."); } continue; } if (attr.ClearCollection && currentValue != null) { bool cleared = TryClearCollection(currentValue); if (cleared) { resetCount++; if (logEach) { Debug.Log($"[ResetStatic] {type.FullName}.{field.Name} collection cleared."); } continue; } } field.SetValue(null, null); resetCount++; if (logEach) { Debug.Log($"[ResetStatic] {type.FullName}.{field.Name} set to null."); } } catch (Exception ex) { Debug.LogWarning($"[ResetStatic] Failed to reset {type.FullName}.{field.Name}: {ex}"); } } } } return resetCount; } private static bool TryClearCollection(object instance) { try { if (instance is System.Collections.IDictionary dictionary) { dictionary.Clear(); return true; } if (instance is System.Collections.IList list) { list.Clear(); return true; } // Try generic ICollection.Clear() var clearMethod = instance.GetType().GetMethod("Clear", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); if (clearMethod != null) { clearMethod.Invoke(instance, null); return true; } } catch (Exception ex) { Debug.LogWarning($"[ResetStatic] Failed to clear collection of type {instance.GetType().FullName}: {ex}"); } return false; } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void AutoResetOnPlay() { #if UNITY_EDITOR bool enabled = UnityEditor.EditorPrefs.GetBool(AutoRunOnPlayPrefsKey, true); if (!enabled) { return; } #endif ResetAll(logEach: false); } #if UNITY_EDITOR public static bool GetAutoRunOnPlay() { return UnityEditor.EditorPrefs.GetBool(AutoRunOnPlayPrefsKey, true); } public static void SetAutoRunOnPlay(bool enabled) { UnityEditor.EditorPrefs.SetBool(AutoRunOnPlayPrefsKey, enabled); } #endif } }