Protfolio-Emanuel-Polsky / Assets / _Project / Code / PathFinding / Systems / CastingCheckSystem.cs
CastingCheckSystem.cs
Raw
using GarmentButton.PhysicFillters;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;


namespace GarmentButton.PathFinding
{
    [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    [BurstCompile]
    public partial struct CastingCheckSystem : ISystem
    {
        private const int CHECK_POINT_BATCH_SIZE = 64;

        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
            var query = SystemAPI.QueryBuilder().WithAll<Grid, GridAdditionalData, UpdatePoints, CastTag>().Build();
            state.RequireForUpdate(query);
            state.RequireForUpdate<SurfaceType>();
        }

        //[BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var surfaceTypeLookUp = SystemAPI.GetComponentLookup<SurfaceType>(true);
            var ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
                .CreateCommandBuffer(state.WorldUnmanaged);
            foreach (var (grid, additional, updatePoints, data, entity) in SystemAPI
                         .Query<RefRW<Grid>, RefRW<GridAdditionalData>, RefRO<UpdatePoints>, RefRO<GridData>>()
                         .WithAll<CastTag>().WithEntityAccess())
            {
                ecb.RemoveComponent<CastTag>(entity);
                var lenght = updatePoints.ValueRO.Indexes.Length;
                var physicsWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>();
                if (lenght > 0)
                {
                    state.Dependency = new CheckPoint
                    {
                        Points = grid.ValueRO.Value,
                        Size = data.ValueRO.CellSize,
                        CanBeWalked = additional.ValueRW.Types,
                        SurfaceLookUp = surfaceTypeLookUp,
                        Physics = physicsWorld.PhysicsWorld,
                        Indexes = updatePoints.ValueRO.Indexes.AsReadOnly()
                    }.ScheduleParallel(lenght, CHECK_POINT_BATCH_SIZE, state.Dependency);
                }

                state.Dependency = new SetUpdateCheck
                {
                    GridEntity = entity,
                    ECB = ecb,
                }.Schedule(state.Dependency);
            }
        }

        [BurstCompile]
        public partial struct CheckPoint : IJobFor
        {
            [ReadOnly] public BlobAssetReference<PointPathBlobAsset> Points;
            [ReadOnly] public float Size;
            [ReadOnly] public ComponentLookup<SurfaceType> SurfaceLookUp;
            [NativeDisableParallelForRestriction]
            public NativeArray<GroundType> CanBeWalked;
            [ReadOnly] public PhysicsWorld Physics;
            [ReadOnly] public NativeArray<ushort>.ReadOnly Indexes;

            public const GroundType DEFUALT_STATE = GroundType.Air;

            public void Execute(int indexe)
            {
                var index = Indexes[indexe];
                var position = Points.Value.Array[index];
                var state = DEFUALT_STATE;
                var position3D = new float3(position.X, position.Y, position.Z) * 0.1f;

                var filter = new CollisionFilter
                {
                    BelongsTo = (uint)CollisionLayer.Trigger,
                    CollidesWith = (uint)(CollisionLayer.Ground) | (uint)(CollisionLayer.Obstacle) |
                                   (uint)(CollisionLayer.AIGround),
                };
                var raycast = Physics.CastRay(new RaycastInput
                {
                    Start = position3D + new float3(0, 10f, 0),
                    End = position3D - new float3(0, 10f, 0),
                    Filter = filter,
                }, out var raycastHit);
                if (!raycast)
                {
                    CanBeWalked[index] = GroundType.Air;
                    return;
                }

                var hits = new NativeList<DistanceHit>(Allocator.Temp);
                var isHit = Physics.OverlapBox(position3D, quaternion.identity, new float3(Size, Size, Size) * 0.5f,
                    ref hits, filter);
                if (!isHit)
                {
                    CanBeWalked[index] = GroundType.Air;
                    hits.Dispose();

                    return;
                }

                for (int i = 0; i < hits.Length; i++)
                {
                    var entity = hits[i].Entity;
                    if (!SurfaceLookUp.HasComponent(entity))
                        continue;

                    var type = SurfaceLookUp.GetRefRO(entity);
                    if ((byte)type.ValueRO.Value <= (byte)state)
                        continue;

                    state = type.ValueRO.Value;
                }

                hits.Dispose();
                CanBeWalked[index] = state;
            }
        }

        [BurstCompile]
        public partial struct SetUpdateCheck : IJob
        {
            public EntityCommandBuffer ECB;
            public Entity GridEntity;

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