chunk 1: core gameplay scripts scenes runtime assets

This commit is contained in:
2026-04-06 11:02:34 +03:00
parent fa0388bc79
commit 0d11a097d8
703 changed files with 2292651 additions and 0 deletions

View File

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