using UnityEngine; using System.Collections.Generic; /// /// EntityRegistry — Zero-allocation replacement for FindObjectsOfType. /// Each MonoBehaviour type auto-registers in OnEnable/OnDisable via EntityRegistryMember. /// Access all instances via EntityRegistry.All (read-only list, no allocation). /// /// Usage: /// 1) Add EntityRegistryMember component, or /// 2) Call EntityRegistry.Register(this) in OnEnable / Unregister in OnDisable /// 3) Query: foreach (var bag in EntityRegistry.All) { ... } /// public static class EntityRegistry where T : class { private static readonly List _instances = new List(32); private static readonly List _readOnly = _instances; // Same ref, cast prevents mutation at call sites /// All currently active instances. Do NOT modify this list. public static List All => _readOnly; /// Alias for All — convenience method matching GetAll() convention. public static List GetAll() => _readOnly; /// Number of active instances. public static int Count => _instances.Count; public static void Register(T instance) { if (instance != null && !_instances.Contains(instance)) _instances.Add(instance); } public static void Unregister(T instance) { _instances.Remove(instance); } /// /// Find nearest instance to a world position. /// Returns null if no instances. O(n) but n is small (≤10 for bags/characters). /// public static T FindNearest(Vector3 position, System.Func getPosition, System.Func filter = null) { T nearest = null; float nearestSqrDist = float.MaxValue; for (int i = 0; i < _instances.Count; i++) { T instance = _instances[i]; if (instance == null) continue; if (filter != null && !filter(instance)) continue; float sqrDist = (getPosition(instance) - position).sqrMagnitude; if (sqrDist < nearestSqrDist) { nearestSqrDist = sqrDist; nearest = instance; } } return nearest; } /// /// Find all instances within radius. Uses pre-allocated result list to avoid allocation. /// Caller should process results immediately (list is reused). /// private static readonly List _withinRadiusResults = new List(16); public static List FindWithinRadius(Vector3 position, float radius, System.Func getPosition, System.Func filter = null) { _withinRadiusResults.Clear(); float sqrRadius = radius * radius; for (int i = 0; i < _instances.Count; i++) { T instance = _instances[i]; if (instance == null) continue; if (filter != null && !filter(instance)) continue; float sqrDist = (getPosition(instance) - position).sqrMagnitude; if (sqrDist <= sqrRadius) _withinRadiusResults.Add(instance); } return _withinRadiusResults; } /// Call on scene unload to prevent stale references. public static void Clear() => _instances.Clear(); }