using GarmentButton.FlatenArray; using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Jobs; namespace GarmentButton.PathFinding { [BurstCompile] [UpdateBefore(typeof(CalculatePathSystem))] public partial struct NearEdgeSystem : ISystem { private const int CHECK_EDGE_BATCH_SIZE = 64; [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); var query = SystemAPI.QueryBuilder().WithAll() .WithNone().Build(); state.RequireForUpdate(query); } [BurstCompile] public void OnUpdate(ref SystemState state) { var ecb = SystemAPI.GetSingleton() .CreateCommandBuffer(state.WorldUnmanaged); var gridEntity = SystemAPI.GetSingletonEntity(); var gridData = SystemAPI.GetSingleton(); var updatePoint = SystemAPI.GetComponentRW(gridEntity); var converter = new FlatenFloatArray2D(gridData.GridSize, gridData.CellSize, gridData.Center); var groundType = SystemAPI.GetSingletonRW(); var updateCount = updatePoint.ValueRO.Indexes.Length; if (updateCount > 0) { state.Dependency = new CheckEdgesJob { Converter = converter, Native = groundType.ValueRW.Types, UpdatePoints = updatePoint.ValueRO.Indexes.AsReadOnly(), }.ScheduleParallel(updateCount, CHECK_EDGE_BATCH_SIZE, state.Dependency); } state.Dependency = new FinishGrid { UpdatePoints = updatePoint.ValueRW.Indexes, ECB = ecb, GridEntity = gridEntity, }.Schedule(state.Dependency); } [BurstCompile] public partial struct CheckEdgesJob : IJobFor { [ReadOnly] public FlatenFloatArray2D Converter; [ReadOnly] public NativeArray.ReadOnly UpdatePoints; [NativeDisableParallelForRestriction] public NativeArray Native; public void Execute(int index) { Basic(index); } private void Basic(int requestedIndex) { var pointIndex = UpdatePoints[requestedIndex]; if (Native[pointIndex] != GroundType.Ground) return; var width = Converter.GridSize.x; var height = Converter.GridSize.y; var pointX = pointIndex % width; var pointY = pointIndex / 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 indexSide = neighbourY * width + neighbourX; if (Native[indexSide] != GroundType.Air) continue; Native[pointIndex] = GroundType.NearGround; return; } } } } [BurstCompile] public partial struct FinishGrid : IJob { public EntityCommandBuffer ECB; public Entity GridEntity; [DeallocateOnJobCompletion] public NativeArray UpdatePoints; public void Execute() { ECB.RemoveComponent(GridEntity); ECB.RemoveComponent(GridEntity); } } } }