public static DrawFindPairsConfig DrawFindPairs(CollisionLayer layer) { return(new DrawFindPairsConfig { layerA = layer, hitColor = Color.red, missColor = Color.green, drawMisses = true, isLayerLayer = false }); }
static void CheckLayersAreCompatible(CollisionLayer layerA, CollisionLayer layerB) { if (math.any(layerA.worldMin != layerB.worldMin | layerA.worldAxisStride != layerB.worldAxisStride | layerA.worldSubdivisionsPerAxis != layerB.worldSubdivisionsPerAxis)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException( "The two layers used in the FindPairs operation are not compatible. Please ensure the layers were constructed with identical settings."); #endif } }
public CollisionLayer(CollisionLayer sourceLayer, Allocator allocator) { worldMin = sourceLayer.worldMin; worldAxisStride = sourceLayer.worldAxisStride; worldSubdivisionsPerAxis = sourceLayer.worldSubdivisionsPerAxis; bucketStartsAndCounts = new NativeArray <int2>(sourceLayer.bucketStartsAndCounts, allocator); xmins = new NativeArray <float>(sourceLayer.xmins, allocator); xmaxs = new NativeArray <float>(sourceLayer.xmaxs, allocator); yzminmaxs = new NativeArray <float4>(sourceLayer.yzminmaxs, allocator); bodies = new NativeArray <ColliderBody>(sourceLayer.bodies, allocator); }
/// <summary> /// Request a FindPairs broadphase operation to report pairs between the two layers. Only pairs containing one element from layerA and one element from layerB will be reported. This is the start of a fluent expression. /// </summary> /// <param name="layerA">The first layer in which pairs should be detected</param> /// <param name="layerB">The second layer in which pairs should be detected</param> /// <param name="processor">The job-like struct which should process each pair found</param> public static FindPairsConfig <T> FindPairs <T>(CollisionLayer layerA, CollisionLayer layerB, T processor) where T : struct, IFindPairsProcessor { CheckLayersAreCompatible(layerA, layerB); return(new FindPairsConfig <T> { processor = processor, layerA = layerA, layerB = layerB, isLayerLayer = true, disableEntityAliasChecks = false }); }
private static void EntityAliasCheck(CollisionLayer layer) { var hashSet = new NativeHashSet <Entity>(layer.Count, Allocator.Temp); for (int i = 0; i < layer.Count; i++) { if (!hashSet.Add(layer.bodies[i].entity)) { throw new InvalidOperationException( $"A parallel FindPairs job was scheduled using a layer containing more than one instance of Entity {layer.bodies[i].entity}"); } } }
public static void RunImmediate <T>(CollisionLayer layer, T processor) where T : struct, IFindPairsProcessor { for (int i = 0; i < layer.BucketCount; i++) { var bucket = layer.GetBucketSlices(i); SelfSweep(bucket, processor); } var crossBucket = layer.GetBucketSlices(layer.BucketCount - 1); for (int i = 0; i < layer.BucketCount - 1; i++) { var bucket = layer.GetBucketSlices(i); BipartiteSweep(bucket, crossBucket, processor); } }
public static JobHandle BuildCollisionLayer(EntityQuery query, LayerChunkTypeGroup typeGroup, CollisionLayerSettings settings, Allocator allocator, JobHandle inputDeps, out CollisionLayer collisionLayer) { int count = query.CalculateEntityCount(); collisionLayer = new CollisionLayer(count, settings, allocator); NativeArray <int> layerIndices = new NativeArray <int>(collisionLayer.Count, allocator, NativeArrayOptions.UninitializedMemory); NativeArray <AABB> aabbs = new NativeArray <AABB>(collisionLayer.Count, allocator, NativeArrayOptions.UninitializedMemory); NativeArray <RigidTransform> rigidTransforms = new NativeArray <RigidTransform>(collisionLayer.Count, allocator, NativeArrayOptions.UninitializedMemory); JobHandle jh = new BuildCollisionLayerPart1 { layer = collisionLayer, layerIndices = layerIndices, aabbs = aabbs, rigidTransforms = rigidTransforms, typeGroup = typeGroup }.Schedule(query, inputDeps); jh = new BuildCollisionLayerPart2 { layer = collisionLayer, layerIndices = layerIndices }.Schedule(jh); jh = new BuildCollisionLayerPart3 { layer = collisionLayer, layerIndices = layerIndices, aabbs = aabbs, rigidTranforms = rigidTransforms, typeGroup = typeGroup }.Schedule(query, jh); //layerIndices, aabbs, and rigidTransforms are deallocated in Part3 jh = new BuildCollisionLayerPart4 { layer = collisionLayer }.Schedule(collisionLayer.BucketCount, 1, jh); return(jh); }
public static DrawLayerConfig DrawLayer(CollisionLayer layer) { var colors = new FixedList512 <Color>(); colors.Length = 7; colors[0] = Color.red; colors[1] = Color.green; colors[2] = Color.blue; colors[3] = Color.cyan; colors[4] = Color.yellow; colors[5] = Color.magenta; colors[6] = Color.black; var crossColor = Color.white; return(new DrawLayerConfig { layer = layer, colors = colors, crossColor = crossColor }); }
public static void RunImmediate(CollisionLayer layer, T processor) { int jobIndex = 0; for (int i = 0; i < layer.BucketCount; i++) { var bucket = layer.GetBucketSlices(i); SelfSweep(bucket, jobIndex++, processor); } var crossBucket = layer.GetBucketSlices(layer.BucketCount - 1); for (int i = 0; i < layer.BucketCount - 1; i++) { var bucket = layer.GetBucketSlices(i); BipartiteSweep(bucket, crossBucket, jobIndex++, processor); } }
public static void RunImmediate(this BuildCollisionLayerConfig config, out CollisionLayer layer, Allocator allocator) { config.ValidateSettings(); if (config.hasQueryData) { ThrowEntityQueryInImmediateMode(); layer = default; } else if (config.hasAabbsArray && config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { BuildCollisionLayerInternal.BuildImmediate(layer, config.remapSrcIndices, config.bodies, config.aabbs); } else { var remapArray = new NativeArray <int>(layer.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); BuildCollisionLayerInternal.BuildImmediate(layer, remapArray, config.bodies, config.aabbs); } } else if (config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { BuildCollisionLayerInternal.BuildImmediate(layer, config.remapSrcIndices, config.bodies, config.aabbs); } else { var remapArray = new NativeArray <int>(layer.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); BuildCollisionLayerInternal.BuildImmediate(layer, remapArray, config.bodies, config.aabbs); } } else { ThrowUnknownConfiguration(); layer = default; } }
public static void DrawFindPairs(CollisionLayer layer) { NativeHashMap <Entity, bool> hitmap = new NativeHashMap <Entity, bool>(layer.Count * 2, Allocator.TempJob); NativeArray <DebugFindPairsHitResult> results = new NativeArray <DebugFindPairsHitResult>(layer.Count, Allocator.TempJob); DebugFindPairsProcessor job = new DebugFindPairsProcessor { hits = hitmap }; new DebugFindPairsJob { processor = job, layer = layer }.Run(); new DebugFindPairsProcessResultsJob { layer = layer, hits = hitmap, results = results }.Run(); for (int i = 0; i < results.Length; i++) { DrawAabb(results[i].aabb, results[i].hit ? Color.red : Color.green); } hitmap.Dispose(); results.Dispose(); }
public static void RunImmediate(this BuildCollisionLayerConfig config, out CollisionLayer layer, Allocator allocator) { config.ValidateSettings(); if (config.hasQueryData) { throw new InvalidOperationException("Error: Running immediate mode on an EntityQuery is not supported. Use Run instead."); } else if (config.hasAabbsArray && config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { BuildCollisionLayerInternal.BuildImmediate(layer, config.remapSrcIndices, config.bodies, config.aabbs); } else { var remapArray = new NativeArray <int>(layer.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); BuildCollisionLayerInternal.BuildImmediate(layer, remapArray, config.bodies, config.aabbs); } } else if (config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { BuildCollisionLayerInternal.BuildImmediate(layer, config.remapSrcIndices, config.bodies, config.aabbs); } else { var remapArray = new NativeArray <int>(layer.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); BuildCollisionLayerInternal.BuildImmediate(layer, remapArray, config.bodies, config.aabbs); } } else { throw new InvalidOperationException("Error: Something went wrong with the BuildCollisionError configuration."); } }
private static void EntityAliasCheck(CollisionLayer layerA, CollisionLayer layerB) { var hashSet = new NativeHashSet <Entity>(layerA.Count + layerB.Count, Allocator.Temp); for (int i = 0; i < layerA.Count; i++) { if (!hashSet.Add(layerA.bodies[i].entity)) { //Note: At this point, we know the issue lies exclusively in layerA. throw new InvalidOperationException( $"A parallel FindPairs job was scheduled using a layer containing more than one instance of Entity {layerA.bodies[i].entity}"); } } for (int i = 0; i < layerB.Count; i++) { if (!hashSet.Add(layerB.bodies[i].entity)) { //Note: At this point, it is unknown whether the repeating entity first showed up in layerA or layerB. throw new InvalidOperationException( $"A parallel FindPairs job was scheduled using two layers combined containing more than one instance of Entity {layerB.bodies[i].entity}"); } } }
public static void BuildImmediate(CollisionLayer layer, NativeArray <int> remapSrcArray, NativeArray <ColliderBody> bodies) { var aabbs = new NativeArray <Aabb>(remapSrcArray.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var layerIndices = new NativeArray <int>(remapSrcArray.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var xmins = new NativeArray <float>(remapSrcArray.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var p1 = new Part1FromColliderBodyArrayJob { aabbs = aabbs, colliderBodies = bodies, layer = layer, layerIndices = layerIndices, xmins = xmins }; for (int i = 0; i < layer.Count; i++) { p1.Execute(i); } new Part2Job { layer = layer, layerIndices = layerIndices }.Execute(); var p3 = new Part3Job { layerIndices = layerIndices, unsortedSrcIndices = remapSrcArray }; for (int i = 0; i < layer.Count; i++) { p3.Execute(i); } var p4 = new Part4Job { bucketStartAndCounts = layer.bucketStartsAndCounts, unsortedSrcIndices = remapSrcArray, xmins = xmins }; for (int i = 0; i < layer.BucketCount; i++) { p4.Execute(i); } var p5 = new Part5FromArraysJob { aabbs = aabbs, bodies = bodies, layer = layer, remapSrcIndices = remapSrcArray }; for (int i = 0; i < layer.Count; i++) { p5.Execute(i); } }
public static JobHandle ScheduleParallel(this BuildCollisionLayerConfig config, out CollisionLayer layer, Allocator allocator, JobHandle inputDeps = default) { config.ValidateSettings(); var jh = inputDeps; if (config.hasQueryData) { int count = config.query.CalculateEntityCount(); layer = new CollisionLayer(count, config.settings, allocator); var layerIndices = new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var xmins = new NativeArray <float>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var aos = new NativeArray <BuildCollisionLayerInternal.ColliderAoSData>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> remapSrcIndices = config.hasRemapSrcIndices ? config.remapSrcIndices : new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); jh = new BuildCollisionLayerInternal.Part1FromQueryJob { layer = layer, typeGroup = config.typeGroup, layerIndices = layerIndices, xmins = xmins, colliderAoS = aos }.ScheduleParallel(config.query, jh); jh = new BuildCollisionLayerInternal.Part2Job { layer = layer, layerIndices = layerIndices }.Schedule(jh); jh = new BuildCollisionLayerInternal.Part3Job { layerIndices = layerIndices, unsortedSrcIndices = remapSrcIndices }.ScheduleParallel(count, 512, jh); jh = new BuildCollisionLayerInternal.Part4Job { unsortedSrcIndices = remapSrcIndices, xmins = xmins, bucketStartAndCounts = layer.bucketStartsAndCounts }.ScheduleParallel(layer.BucketCount, 1, jh); jh = new BuildCollisionLayerInternal.Part5FromQueryJob { layer = layer, colliderAoS = aos, remapSrcIndices = remapSrcIndices }.ScheduleParallel(count, 128, jh); if (!config.hasRemapSrcIndices) { jh = remapSrcIndices.Dispose(jh); } return(jh); } else if (config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); int count = config.bodies.Length; var layerIndices = new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var xmins = new NativeArray <float>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> remapSrcIndices = config.hasRemapSrcIndices ? config.remapSrcIndices : new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <Aabb> aabbs = config.hasAabbsArray ? config.aabbs : new NativeArray <Aabb>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); if (config.hasAabbsArray) { jh = new BuildCollisionLayerInternal.Part1FromDualArraysJob { layer = layer, aabbs = aabbs, layerIndices = layerIndices, xmins = xmins }.ScheduleParallel(count, 64, jh); } else { jh = new BuildCollisionLayerInternal.Part1FromColliderBodyArrayJob { layer = layer, aabbs = aabbs, colliderBodies = config.bodies, layerIndices = layerIndices, xmins = xmins }.ScheduleParallel(count, 64, jh); } jh = new BuildCollisionLayerInternal.Part2Job { layer = layer, layerIndices = layerIndices }.Schedule(jh); jh = new BuildCollisionLayerInternal.Part3Job { layerIndices = layerIndices, unsortedSrcIndices = remapSrcIndices }.ScheduleParallel(count, 512, jh); jh = new BuildCollisionLayerInternal.Part4Job { bucketStartAndCounts = layer.bucketStartsAndCounts, unsortedSrcIndices = remapSrcIndices, xmins = xmins }.ScheduleParallel(layer.BucketCount, 1, jh); jh = new BuildCollisionLayerInternal.Part5FromArraysJob { aabbs = aabbs, bodies = config.bodies, layer = layer, remapSrcIndices = remapSrcIndices }.ScheduleParallel(count, 128, jh); if ((!config.hasAabbsArray) && (!config.hasRemapSrcIndices)) { jh = JobHandle.CombineDependencies(remapSrcIndices.Dispose(jh), aabbs.Dispose(jh)); } else if (!config.hasRemapSrcIndices) { jh = remapSrcIndices.Dispose(jh); } else if (!config.hasAabbsArray) { jh = aabbs.Dispose(jh); } return(jh); } else { throw new InvalidOperationException("Something went wrong with the BuildCollisionError configuration."); } }
public static JobHandle ScheduleSingle(this BuildCollisionLayerConfig config, out CollisionLayer layer, Allocator allocator, JobHandle inputDeps = default) { config.ValidateSettings(); var jh = inputDeps; if (config.hasQueryData) { int count = config.count; layer = new CollisionLayer(count, config.settings, allocator); var layerIndices = new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var aos = new NativeArray <BuildCollisionLayerInternal.ColliderAoSData>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var xmins = new NativeArray <float>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> remapSrcIndices = config.hasRemapSrcIndices ? config.remapSrcIndices : new NativeArray <int>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); jh = new BuildCollisionLayerInternal.Part1FromQueryJob { typeGroup = config.typeGroup, layer = layer, layerIndices = layerIndices, colliderAoS = aos, xmins = xmins }.ScheduleSingle(config.query, jh); jh = new BuildCollisionLayerInternal.Part2Job { layer = layer, layerIndices = layerIndices }.Schedule(jh); jh = new BuildCollisionLayerInternal.Part3Job { layerIndices = layerIndices, unsortedSrcIndices = remapSrcIndices }.Schedule(count, jh); jh = new BuildCollisionLayerInternal.Part4Job { bucketStartAndCounts = layer.bucketStartsAndCounts, unsortedSrcIndices = remapSrcIndices, xmins = xmins }.Schedule(count, jh); jh = new BuildCollisionLayerInternal.Part5FromQueryJob { colliderAoS = aos, layer = layer, remapSrcIndices = remapSrcIndices }.Schedule(count, jh); if (!config.hasRemapSrcIndices) { jh = remapSrcIndices.Dispose(jh); } return(jh); } else if (config.hasAabbsArray && config.hasBodiesArray) { layer = new CollisionLayer(config.aabbs.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { jh = new BuildCollisionLayerInternal.BuildFromDualArraysSingleWithRemapJob { layer = layer, aabbs = config.aabbs, bodies = config.bodies, remapSrcIndices = config.remapSrcIndices }.Schedule(jh); } else { jh = new BuildCollisionLayerInternal.BuildFromDualArraysSingleJob { layer = layer, aabbs = config.aabbs, bodies = config.bodies }.Schedule(jh); } return(jh); } else if (config.hasBodiesArray) { layer = new CollisionLayer(config.bodies.Length, config.settings, allocator); if (config.hasRemapSrcIndices) { jh = new BuildCollisionLayerInternal.BuildFromColliderArraySingleWithRemapJob { layer = layer, bodies = config.bodies, remapSrcIndices = config.remapSrcIndices }.Schedule(jh); } else { jh = new BuildCollisionLayerInternal.BuildFromColliderArraySingleJob { layer = layer, bodies = config.bodies }.Schedule(jh); } return(jh); } else { throw new InvalidOperationException("Something went wrong with the BuildCollisionError configuration."); } }