Esempio n. 1
0
        protected override void OnUpdate()
        {
            // A map from entities to arrays of colliders that were not applied to the body during the first pass.
            m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(64, Allocator.Temp); // TODO - add custom data to Physics.Collider?

            // First pass.
            // Convert all editor shape components into colliders, and either apply them to their parent rigid body
            // or store them for building compound colliders in the second pass.
            Entities.ForEach <T>(ConvertShape);

            // Second pass.
            // Merge any leftover colliders into their parent rigid bodies, as compound colliders.
            if (m_ExtraColliders.Length > 0)
            {
                var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp);
                using (keys.Item1)
                {
                    for (var k = 0; k < keys.Item2; ++k)
                    {
                        ComparableEntity entity = keys.Item1[k];
                        var collider            = DstEntityManager.GetComponentData <PhysicsCollider>(entity.Entity);
                        var children            = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp);

                        if (collider.IsValid)
                        {
                            // Include the already assigned collider as a child
                            children.Add(new CompoundCollider.ColliderBlobInstance {
                                Collider = collider.Value, CompoundFromChild = RigidTransform.identity
                            });
                        }

                        byte customData = 0;
                        if (m_ExtraColliders.TryGetFirstValue(entity, out var child, out var iterator))
                        {
                            do
                            {
                                children.Add(child.ColliderBlobInstance);
                                customData &= child.CustomFlags; // TODO: Should be |= ??
                            } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator));
                        }

                        collider.Value = CompoundCollider.Create(children);

                        children.Dispose();

                        DstEntityManager.SetComponentData(entity.Entity, collider);

                        if (customData != 0)
                        {
                            DstEntityManager.AddOrSetComponent(entity.Entity, new PhysicsCustomData {
                                Value = customData
                            });
                        }
                    }
                }
            }
            m_ExtraColliders.Dispose();
        }
        protected override void OnUpdate()
        {
            var shapeQuery = EntityManager.CreateEntityQuery(ComponentType.ReadOnly <T>());
            var shapeCount = shapeQuery.CalculateEntityCount();

            // A map from entities to arrays of colliders
            m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(shapeCount, Allocator.Temp);

            // Lists to store input data for deferred convex and mesh jobs
            const int defaultPointsPerShape = 1024;

            m_ConvexColliderJobs   = new NativeList <ConvertConvexColliderInput>(shapeCount, Allocator.TempJob);
            m_ConvexColliderPoints = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob);

            m_MeshColliderJobs     = new NativeList <ConvertMeshColliderInput>(shapeCount, Allocator.TempJob);
            m_MeshColliderVertices = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob);
            m_MeshColliderIndices  = new NativeList <int>(shapeCount * defaultPointsPerShape / 2, Allocator.TempJob);

            // First pass.
            // Convert all shape authoring components into colliders, and collect them for each primary body
            Entities.ForEach <T>(ConvertShape);

            // Second pass.
            // Produce all convex and mesh collider blobs in parallel
            const int arrayLength     = 5;
            var       convexColliders =
                new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_ConvexColliderJobs.Length, Allocator.TempJob);
            var convexJob = new ProduceConvexCollidersJob
            {
                InputParameters = m_ConvexColliderJobs,
                AllPoints       = m_ConvexColliderPoints,
                Output          = convexColliders
            }.Schedule(m_ConvexColliderJobs.Length, arrayLength);

            var meshColliders =
                new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_MeshColliderJobs.Length, Allocator.TempJob);
            var meshJob = new ProduceMeshCollidersJob
            {
                InputParameters = m_MeshColliderJobs,
                AllVertices     = m_MeshColliderVertices,
                AllIndices      = m_MeshColliderIndices,
                Output          = meshColliders
            }.Schedule(m_MeshColliderJobs.Length, arrayLength);

            JobHandle.CombineDependencies(convexJob, meshJob).Complete();

            AppendLeafShapeDataToShapeMap(convexColliders, m_ExtraColliders, m_ConvexShapes);
            convexColliders.Dispose();

            AppendLeafShapeDataToShapeMap(meshColliders, m_ExtraColliders, m_MeshShapes);
            meshColliders.Dispose();

            // Final pass.
            // Assign PhysicsCollider components to rigid bodies, merging multiples into compounds as needed
            var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp);

            using (keys.Item1)
            {
                for (var k = 0; k < keys.Item2; ++k)
                {
                    ComparableEntity body = keys.Item1[k];
                    var collider          = DstEntityManager.HasComponent <PhysicsCollider>(body.Entity)
                        ? DstEntityManager.GetComponentData <PhysicsCollider>(body.Entity)
                        : new PhysicsCollider();
                    var children = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp);

                    // collect any existing valid shapes
                    if (collider.IsValid)
                    {
                        ColliderType colliderType;
                        unsafe { colliderType = collider.ColliderPtr->Type; }

                        // if there is already a compound, add its leaves to the list of children
                        if (colliderType == ColliderType.Compound)
                        {
                            unsafe
                            {
                                var existingChildren = ((CompoundCollider *)collider.ColliderPtr)->Children;
                                for (int i = 0, count = existingChildren.Length; i < count; ++i)
                                {
                                    children.Add(new CompoundCollider.ColliderBlobInstance
                                    {
                                        Collider = BlobAssetReference <Collider> .Create(
                                            existingChildren[i].Collider,
                                            existingChildren[i].Collider->MemorySize
                                            ),
                                        CompoundFromChild = existingChildren[i].CompoundFromChild
                                    });
                                }
                            }
                        }
                        // otherwise add the single collider to the list of children
                        else
                        {
                            children.Add(
                                new CompoundCollider.ColliderBlobInstance
                            {
                                Collider          = collider.Value,
                                CompoundFromChild = RigidTransform.identity
                            }
                                );
                        }
                    }

                    // if collider is already valid, a shape already existed from another system
                    var isSingleShapeOnPrimaryBody = !collider.IsValid;
                    // collect all children found by this system
                    if (m_ExtraColliders.TryGetFirstValue(body, out var child, out var iterator))
                    {
                        do
                        {
                            children.Add(child.ColliderBlobInstance);
                            isSingleShapeOnPrimaryBody &= child.LeafEntity.Equals(body.Entity);
                        } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator));
                    }

                    // if there is a single shape on the primary body, use it as-is, otherwise create a compound
                    // (assume a single leaf should still be a compound so that local offset values in authoring representation are retained)
                    collider.Value = isSingleShapeOnPrimaryBody
                        ? children[0].Collider
                        : CompoundCollider.Create(children);

                    children.Dispose();

                    DstEntityManager.AddOrSetComponent(body.Entity, collider);
                }
            }

            m_ConvexShapes.Clear();
            m_ConvexColliderJobs.Dispose();
            m_ConvexColliderPoints.Dispose();

            m_MeshShapes.Clear();
            m_MeshColliderJobs.Dispose();
            m_MeshColliderVertices.Dispose();
            m_MeshColliderIndices.Dispose();
        }