using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Jobs; using Unity.Mathematics; using Unity.Transforms; namespace HappyForest.Prototypen { // Pille-gegen-Pille Kollision. Bewusst als einfacher O(n^2) Burst-Job gebaut, // damit man per "K"-Taste sauber A/B vergleichen kann, was die Kollisionsprüfung // an Performance kostet. Läuft nur, wenn PilleCollisionEnabled = true ist. // (Für sehr große Mengen, z.B. >10.000, wäre ein Spatial-Grid der nächste Schritt.) public partial struct PilleCollisionSystem : ISystem { public void OnCreate(ref SystemState state) { state.RequireForUpdate(); } public void OnUpdate(ref SystemState state) { var config = SystemAPI.GetSingleton(); if (!config.PilleCollisionEnabled) return; var query = SystemAPI.QueryBuilder().WithAll().Build(); int count = query.CalculateEntityCount(); if (count < 2) return; var transforms = query.ToComponentDataArray(Allocator.TempJob); var pilles = query.ToComponentDataArray(Allocator.TempJob); float radiusSum = config.PilleRadius * 2f; var job = new ResolvePairCollisionsJob { Transforms = transforms, Pilles = pilles, RadiusSq = radiusSum * radiusSum }; state.Dependency = job.Schedule(state.Dependency); state.Dependency.Complete(); query.CopyFromComponentDataArray(pilles); transforms.Dispose(); pilles.Dispose(); } } [BurstCompile] public struct ResolvePairCollisionsJob : IJob { [ReadOnly] public NativeArray Transforms; public NativeArray Pilles; public float RadiusSq; public void Execute() { int count = Transforms.Length; for (int i = 0; i < count; i++) { for (int j = i + 1; j < count; j++) { float3 delta = Transforms[i].Position - Transforms[j].Position; float distSq = math.lengthsq(delta); if (distSq < RadiusSq && distSq > 0.0001f) { float3 normal = math.normalize(delta); var pi = Pilles[i]; var pj = Pilles[j]; pi.Velocity = math.reflect(pi.Velocity, normal); pj.Velocity = math.reflect(pj.Velocity, -normal); Pilles[i] = pi; Pilles[j] = pj; } } } } } }