Protfolio-Emanuel-Polsky / Assets / _Project / Code / PathFinding / Systems / NearEdgeSystem.cs
NearEdgeSystem.cs
Raw
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<Grid>();
            state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
            var query = SystemAPI.QueryBuilder().WithAll<GridData, GridAdditionalData, UpdateCheck, UpdatePoints>()
                .WithNone<CastTag>().Build();
            state.RequireForUpdate(query);
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
                .CreateCommandBuffer(state.WorldUnmanaged);
            var gridEntity = SystemAPI.GetSingletonEntity<GridData>();
            var gridData = SystemAPI.GetSingleton<GridData>();
            var updatePoint = SystemAPI.GetComponentRW<UpdatePoints>(gridEntity);
            var converter = new FlatenFloatArray2D(gridData.GridSize, gridData.CellSize, gridData.Center);
            var groundType = SystemAPI.GetSingletonRW<GridAdditionalData>();
            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<ushort>.ReadOnly UpdatePoints;
            [NativeDisableParallelForRestriction]
            public NativeArray<GroundType> 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<ushort> UpdatePoints;

            public void Execute()
            {
                ECB.RemoveComponent<UpdateCheck>(GridEntity);
                ECB.RemoveComponent<UpdatePoints>(GridEntity);
            }
        }
    }
}