Files
test/Assets/PerfectWorld/Scripts/Utils/ResetStaticUtility.cs
T
2025-11-13 18:57:24 +07:00

182 lines
4.0 KiB
C#

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<Assembly, bool> 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<ResetStaticAttribute>(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<T>.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
}
}