using GarmentButton.FlatenArray; using Unity.Burst; using Unity.Collections; using Unity.Entities; namespace GarmentButton.PathFinding { [BurstCompile] public partial struct UpdateSpecificPointSystem : ISystem { private const int UPDATE_RADIUS = 5; [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); state.RequireForUpdate(); } [BurstCompile] public void OnUpdate(ref SystemState state) { var grid = SystemAPI.GetSingleton(); var entityGrid = SystemAPI.GetSingletonEntity(); if (SystemAPI.HasComponent(entityGrid) || SystemAPI.HasComponent(entityGrid) || SystemAPI.HasComponent(entityGrid)) return; var ecb = new EntityCommandBuffer(Allocator.Temp); var converter = new FlatenFloatArray2D(grid.GridSize, grid.CellSize, grid.Center); var gridLength = grid.GridSize.x * grid.GridSize.y; var initialCapacity = gridLength < 256 ? gridLength : 256; var visited = new NativeArray(gridLength, Allocator.Temp, NativeArrayOptions.ClearMemory); var addedPoints = new NativeList(initialCapacity, Allocator.Temp); var currentPoints = new NativeList(initialCapacity, Allocator.Temp); var nextPoints = new NativeList(initialCapacity, Allocator.Temp); foreach (var (updatePosition, entity) in SystemAPI.Query>().WithEntityAccess()) { var starIndex = converter.GetCellAtPosition(updatePosition.ValueRO.Value); currentPoints.Clear(); nextPoints.Clear(); if (TryAddPoint(starIndex, visited, ref addedPoints)) currentPoints.Add(starIndex); for (var radius = 0; radius < UPDATE_RADIUS; radius++) { for (var i = 0; i < currentPoints.Length; i++) { AddNeighbours(currentPoints[i], grid.GridSize.x, grid.GridSize.y, visited, ref addedPoints, ref nextPoints); } var tempPoints = currentPoints; currentPoints = nextPoints; nextPoints = tempPoints; nextPoints.Clear(); } ecb.RemoveComponent(entity); } if (addedPoints.Length > 0) { ecb.AddComponent(entityGrid, new UpdatePoints { Indexes = new NativeArray(addedPoints.AsArray(), Allocator.Persistent) }); ecb.AddComponent(entityGrid); } ecb.Playback(state.EntityManager); ecb.Dispose(); visited.Dispose(); currentPoints.Dispose(); nextPoints.Dispose(); addedPoints.Dispose(); } private bool TryAddPoint(int index, NativeArray visited, ref NativeList addedPoints) { if (visited[index] != 0) return false; visited[index] = 1; addedPoints.Add((ushort)index); return true; } private void AddNeighbours(int currentNodeIndex, int width, int height, NativeArray visited, ref NativeList addedPoints, ref NativeList nextPoints) { var pointX = currentNodeIndex % width; var pointY = currentNodeIndex / width; for (var yOffset = -1; yOffset <= 1; yOffset++) { for (var xOffset = -1; xOffset <= 1; xOffset++) { if ((xOffset | yOffset) == 0) continue; var neighbourX = pointX + xOffset; var neighbourY = pointY + yOffset; if ((uint)neighbourX >= (uint)width || (uint)neighbourY >= (uint)height) continue; var neighbourIndex = neighbourY * width + neighbourX; if (!TryAddPoint(neighbourIndex, visited, ref addedPoints)) continue; nextPoints.Add(neighbourIndex); } } } } }