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