JobHandle ProduceMeshColliders( NativeHashMap <Hash128, MeshInput> inputs, NativeList <float3> vertices, NativeList <int3> indices, out NativeHashMap <Hash128, BlobAssetReference <Collider> > meshColliders, JobHandle inputDeps = default ) { // create collider blob assets var meshCollidersArray = new NativeArray <KeyValuePair <Hash128, BlobAssetReference <Collider> > >(inputs.Count(), Allocator.TempJob); const int arrayLength = 5; var jobHandle = new ProduceMeshCollidersJob { InputKeys = inputs.GetKeyArray(Allocator.TempJob), InputValues = inputs.GetValueArray(Allocator.TempJob), AllVertices = vertices, AllIndices = indices, Output = meshCollidersArray }.Schedule(inputs.Count(), arrayLength, inputDeps); // put blob assets into hash map meshColliders = new NativeHashMap <Hash128, BlobAssetReference <Collider> >(inputs.Count(), Allocator.TempJob); jobHandle = new ConvertToHashMapJob <Hash128, BlobAssetReference <Collider> > { Input = meshCollidersArray, Output = meshColliders }.Schedule(jobHandle); return(jobHandle); }
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(); }