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);
}
}
}
}