/// <summary>
 /// Request a FindPairs broadphase operation to report pairs within the layer. This is the start of a fluent expression.
 /// </summary>
 /// <param name="layer">The 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 layer, T processor) where T : struct, IFindPairsProcessor
 {
     return(new FindPairsConfig <T>
     {
         processor = processor,
         layerA = layer,
         isLayerLayer = false,
         disableEntityAliasChecks = 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 static DrawFindPairsConfig DrawFindPairs(CollisionLayer layer)
 {
     return(new DrawFindPairsConfig
     {
         layerA = layer,
         hitColor = Color.red,
         missColor = Color.green,
         drawMisses = true,
         isLayerLayer = false
     });
 }
Beispiel #4
0
        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
     });
 }
Beispiel #6
0
            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}");
                    }
                }
            }
Beispiel #7
0
            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, false);
                }

                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, false);
                }
            }
        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
            });
        }
Beispiel #9
0
        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;
            }
        }
Beispiel #10
0
            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);
            }
        }
Beispiel #12
0
        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, 1, 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.");
            }
        }
Beispiel #13
0
        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
                }.Schedule(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(layer.BucketCount, 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.");
            }
        }