protected override void OnUpdate() { Entities.ForEach( (PhysicsBody body) => { if (!body.enabled) { return; } var entity = GetPrimaryEntity(body.gameObject); if (body.MotionType == BodyMotionType.Static) { return; } // Build mass component var massProperties = DstEntityManager.GetComponentData <PhysicsCollider>(entity).MassProperties; if (body.OverrideDefaultMassDistribution) { massProperties.MassDistribution = body.CustomMassDistribution; // Increase the angular expansion factor to account for the shift in center of mass massProperties.AngularExpansionFactor += math.length(massProperties.MassDistribution.Transform.pos - body.CustomMassDistribution.Transform.pos); } DstEntityManager.AddOrSetComponent(entity, body.MotionType == BodyMotionType.Dynamic ? PhysicsMass.CreateDynamic(massProperties, body.Mass) : PhysicsMass.CreateKinematic(massProperties)); DstEntityManager.AddOrSetComponent(entity, new PhysicsVelocity { Linear = body.InitialLinearVelocity, Angular = body.InitialAngularVelocity }); if (body.MotionType == BodyMotionType.Dynamic) { // TODO make these optional in editor? DstEntityManager.AddOrSetComponent(entity, new PhysicsDamping { Linear = body.LinearDamping, Angular = body.AngularDamping }); if (body.GravityFactor != 1) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = body.GravityFactor }); } } else if (body.MotionType == BodyMotionType.Kinematic) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = 0 }); } } ); }
protected override void OnUpdate() { Entities.ForEach( (LegacyRigidBody body) => { var entity = GetPrimaryEntity(body.gameObject); // prefer conversions from non-legacy data if they have already been performed if (DstEntityManager.HasComponent <PhysicsVelocity>(entity)) { return; } DstEntityManager.PostProcessTransformComponents( entity, body.transform, body.isKinematic ? BodyMotionType.Kinematic : BodyMotionType.Dynamic ); if (body.gameObject.isStatic) { return; } // Build mass component var massProperties = MassProperties.UnitSphere; if (DstEntityManager.HasComponent <PhysicsCollider>(entity)) { // Build mass component massProperties = DstEntityManager.GetComponentData <PhysicsCollider>(entity).MassProperties; } // n.b. no way to know if CoM was manually adjusted, so all legacy Rigidbody objects use auto CoM DstEntityManager.AddOrSetComponent(entity, !body.isKinematic ? PhysicsMass.CreateDynamic(massProperties, body.mass) : PhysicsMass.CreateKinematic(massProperties)); DstEntityManager.AddOrSetComponent(entity, new PhysicsVelocity()); if (!body.isKinematic) { DstEntityManager.AddOrSetComponent(entity, new PhysicsDamping { Linear = body.drag, Angular = body.angularDrag }); if (!body.useGravity) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = 0f }); } } else { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = 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(); }
void ConvertShape(T shape) { if (!ShouldConvertShape(shape)) { return; } var body = GetPrimaryBody(shape); var entity = GetPrimaryEntity(body); var colliderBlob = ProduceColliderBlob(shape); if (!DstEntityManager.HasComponent <PhysicsCollider>(entity)) { DstEntityManager.AddComponentData(entity, new PhysicsCollider()); } var collider = DstEntityManager.GetComponentData <PhysicsCollider>(entity); var customFlags = GetCustomFlags(shape); if (!collider.IsValid && body == shape.gameObject) { // Shape is on same object as body, therefore has no relative transform. // Set it directly into the entity component. collider.Value = colliderBlob; DstEntityManager.SetComponentData(entity, collider); if (customFlags != 0) { DstEntityManager.AddOrSetComponent(entity, new PhysicsCustomData { Value = customFlags }); } } else { // Body has multiple shapes or may have a relative transform. // Store it for building compound colliders in the second pass. // Note: Not including relative scale, since that is baked into the colliders var worldFromBody = new RigidTransform(body.transform.rotation, body.transform.position); var worldFromShape = new RigidTransform(shape.transform.rotation, shape.transform.position); var compoundFromChild = math.mul(math.inverse(worldFromBody), worldFromShape); m_ExtraColliders.Add( new ComparableEntity { Entity = entity }, new LeafShapeData { ColliderBlobInstance = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = compoundFromChild, Collider = colliderBlob }, CustomFlags = customFlags } ); } }
protected override void OnUpdate() { Entities.ForEach( (Rigidbody body) => { var entity = GetPrimaryEntity(body.gameObject); DstEntityManager.AddOrSetComponent(entity, new PhysicsCollider()); } ); }
protected override void OnUpdate() { Entities.ForEach( (PhysicsBody body) => { if (!body.enabled) { return; } var entity = GetPrimaryEntity(body.gameObject); DstEntityManager.AddOrSetComponent(entity, new PhysicsCollider()); } ); }
void CreateJointEntity(GameObject gameObject, BlobAssetReference <JointData> jointData, Entity entityA, Entity entityB, bool enableCollision) { var componentData = new PhysicsJoint { JointData = jointData, EntityA = entityA, EntityB = entityB, EnableCollision = enableCollision ? 1 : 0, }; Entity jointEntity = CreateAdditionalEntity(gameObject); #if UNITY_EDITOR var nameEntityA = DstEntityManager.GetName(entityA); var nameEntityB = entityB == Entity.Null ? "PhysicsWorld" : DstEntityManager.GetName(entityB); DstEntityManager.SetName(jointEntity, $"Joining {nameEntityA} + {nameEntityB}"); #endif DstEntityManager.AddOrSetComponent(jointEntity, componentData); }
protected override void OnUpdate() { Profiler.BeginSample("Build Compound Colliders"); // Assign PhysicsCollider components to rigid body entities, merging multiples into compounds as needed var changedBodies = m_ChangedLeavesByBody.GetUniqueKeyArray(Allocator.Temp); using (changedBodies.Item1) { // Loop through all the bodies that changed for (var k = 0; k < changedBodies.Item2; ++k) { var body = changedBodies.Item1[k]; var collider = DstEntityManager.HasComponent <PhysicsCollider>(body) ? DstEntityManager.GetComponentData <PhysicsCollider>(body) : new PhysicsCollider(); var children = new NativeHashMap <ColliderInstanceId, ChildInstance>(16, Allocator.Temp); var isLeafEntityBody = true; // The current body that changed may have one or more shape to process, loop through all of them if (m_ChangedLeavesByBody.TryGetFirstValue(body, out var shape, out var iterator)) { do { var replaced = false; // Look for existing known shape. For this there is no magic, O(n) scan on the body's shapes if (m_AllLeafCollidersByBody.TryGetFirstValue(body, out var existingShape, out var existingIterator)) { do { // If the current child is the one we care about then replace its associated data if (existingShape.ShapeEntity.Equals(shape.ShapeEntity)) { m_AllLeafCollidersByBody.SetValue(shape, existingIterator); replaced = true; break; } }while (m_AllLeafCollidersByBody.TryGetNextValue(out existingShape, ref existingIterator)); } // Add the shape if it did not exist already if (!replaced) { m_AllLeafCollidersByBody.Add(body, shape); } // Add the shape to the list of children to process later if (BlobComputationContext.GetBlobAsset(shape.Hash, out var blobAsset)) { var child = new ChildInstance { Hash = shape.Hash, Child = new CompoundCollider.ColliderBlobInstance { Collider = blobAsset, CompoundFromChild = shape.BodyFromShape } }; children.Add(shape.ToColliderInstanceId(), child); isLeafEntityBody &= shape.ShapeEntity.Equals(body); } else { var gameObject = m_EndColliderConversionSystem.GetConvertedAuthoringComponent(shape.ConvertedAuthoringComponentIndex).gameObject; Debug.LogWarning($"Couldn't convert Collider for GameObject '{gameObject.name}'."); } }while (m_ChangedLeavesByBody.TryGetNextValue(out shape, ref iterator)); } // Add all children that did not change if (m_AllLeafCollidersByBody.TryGetFirstValue(body, out shape, out var it)) { do { isLeafEntityBody &= shape.ShapeEntity.Equals(body); if (BlobComputationContext.GetBlobAsset(shape.Hash, out var blobAsset)) { var child = new ChildInstance { Hash = shape.Hash, Child = new CompoundCollider.ColliderBlobInstance { Collider = blobAsset, CompoundFromChild = shape.BodyFromShape } }; children.TryAdd(shape.ToColliderInstanceId(), child); } }while (m_AllLeafCollidersByBody.TryGetNextValue(out shape, ref it)); } // Get the list of colliders to (re)build var colliders = children.GetValueArray(Allocator.TempJob); // If the leaf is the same entity as the body, and there is a single shape, 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) if (colliders.Length > 0) { if (isLeafEntityBody && colliders.Length == 1) { collider.Value = colliders[0].Child.Collider; } else { // sort children by hash to ensure deterministic results // required because instance ID on hash map key is non-deterministic between runs, // but it affects the order of values returned by NativeHashMap<T>.GetValueArray() colliders.Sort(); // otherwise it is a compound var childHashes = new NativeArray <Hash128>(colliders.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var childOffsets = new NativeArray <RigidTransform>(colliders.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var childBlobs = new NativeArray <CompoundCollider.ColliderBlobInstance>(colliders.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); for (var i = 0; i < children.Count(); ++i) { childHashes[i] = colliders[i].Hash; childOffsets[i] = colliders[i].Child.CompoundFromChild; childBlobs[i] = colliders[i].Child; } Profiler.BeginSample("Generate Hash for Compound"); var compoundHash = new NativeArray <Hash128>(1, Allocator.TempJob); new HashChildrenJob { ChildHashes = childHashes, ChildOffsets = childOffsets, Output = compoundHash }.Run(); Profiler.EndSample(); var gameObject = m_EndColliderConversionSystem.GetConvertedAuthoringComponent(shape.ConvertedBodyTransformIndex).gameObject; BlobComputationContext.AssociateBlobAssetWithUnityObject(compoundHash[0], gameObject); if (!BlobComputationContext.NeedToComputeBlobAsset(compoundHash[0])) { BlobComputationContext.GetBlobAsset(compoundHash[0], out collider.Value); } else { BlobComputationContext.AddBlobAssetToCompute(compoundHash[0], 0); using (var compound = new NativeArray <BlobAssetReference <Collider> >(1, Allocator.TempJob)) { new CreateCompoundJob { Children = childBlobs, Output = compound }.Run(); collider.Value = compound[0]; BlobComputationContext.AddComputedBlobAsset(compoundHash[0], collider.Value); } } compoundHash.Dispose(); childBlobs.Dispose(); } } colliders.Dispose(); children.Dispose(); DstEntityManager.AddOrSetComponent(body, collider); } } m_ChangedLeavesByBody.Clear(); Profiler.EndSample(); }
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(); }
protected override void OnUpdate() { Entities.ForEach( (StaticOptimizeEntity staticOptimized) => { var entity = GetPrimaryEntity(staticOptimized.gameObject); if (DstEntityManager.HasComponent <PhysicsCollider>(entity)) { DstEntityManager.PostProcessTransformComponents(entity, staticOptimized.transform, BodyMotionType.Static); } } ); Entities.ForEach( (PhysicsBodyAuthoring body) => { var entity = GetPrimaryEntity(body.gameObject); DstEntityManager.PostProcessTransformComponents(entity, body.transform, body.MotionType); var customTags = body.CustomTags; if (!customTags.Equals(CustomPhysicsBodyTags.Nothing)) { DstEntityManager.AddOrSetComponent(entity, new PhysicsCustomTags { Value = customTags.Value }); } if (body.MotionType == BodyMotionType.Static) { return; } var massProperties = MassProperties.UnitSphere; if (DstEntityManager.HasComponent <PhysicsCollider>(entity)) { // Build mass component massProperties = DstEntityManager.GetComponentData <PhysicsCollider>(entity).MassProperties; } if (body.OverrideDefaultMassDistribution) { massProperties.MassDistribution = body.CustomMassDistribution; // Increase the angular expansion factor to account for the shift in center of mass massProperties.AngularExpansionFactor += math.length(massProperties.MassDistribution.Transform.pos - body.CustomMassDistribution.Transform.pos); } DstEntityManager.AddOrSetComponent(entity, body.MotionType == BodyMotionType.Dynamic ? PhysicsMass.CreateDynamic(massProperties, body.Mass) : PhysicsMass.CreateKinematic(massProperties)); var physicsVelocity = new PhysicsVelocity { Linear = body.InitialLinearVelocity, Angular = body.InitialAngularVelocity }; DstEntityManager.AddOrSetComponent(entity, physicsVelocity); if (body.MotionType == BodyMotionType.Dynamic) { // TODO make these optional in editor? DstEntityManager.AddOrSetComponent(entity, new PhysicsDamping { Linear = body.LinearDamping, Angular = body.AngularDamping }); if (body.GravityFactor != 1) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = body.GravityFactor }); } } else if (body.MotionType == BodyMotionType.Kinematic) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor { Value = 0 }); } if (body.Smoothing != BodySmoothing.None) { DstEntityManager.AddOrSetComponent(entity, new PhysicsGraphicalSmoothing()); if (body.Smoothing == BodySmoothing.Interpolation) { DstEntityManager.AddComponentData(entity, new PhysicsGraphicalInterpolationBuffer { PreviousTransform = Math.DecomposeRigidBodyTransform(body.transform.localToWorldMatrix), PreviousVelocity = physicsVelocity, }); } } } ); }
protected override void OnUpdate() { Entities.ForEach((UnityEngine.Rigidbody2D rigidbody) => { // We don't convert a Rigidbody2D if it's not Simulated. if (!rigidbody.simulated) { return; } var entity = GetPrimaryEntity(rigidbody); var bodyType = rigidbody.bodyType; // There's no components to define a Static rigidbody or its properties. if (bodyType != UnityEngine.RigidbodyType2D.Static) { // Velocity. if (!DstEntityManager.HasComponent <PhysicsVelocity>(entity)) { DstEntityManager.AddComponentData(entity, new PhysicsVelocity { Linear = rigidbody.velocity, Angular = rigidbody.angularVelocity }); } var massProperties = MassProperties.Default; // Fetch mass properties from any available collider. if (DstEntityManager.HasComponent <PhysicsColliderBlob>(entity)) { var collider = DstEntityManager.GetComponentData <PhysicsColliderBlob>(entity).Collider; massProperties = collider.IsCreated ? collider.Value.MassProperties : MassProperties.Default; } // Dynamic. if (bodyType == UnityEngine.RigidbodyType2D.Dynamic) { DstEntityManager.AddOrSetComponent(entity, PhysicsMass.CreateDynamic(massProperties, rigidbody.mass)); if (!DstEntityManager.HasComponent <PhysicsGravity>(entity)) { DstEntityManager.AddComponentData(entity, new PhysicsGravity { Scale = rigidbody.gravityScale }); } if (!DstEntityManager.HasComponent <PhysicsDamping>(entity)) { DstEntityManager.AddComponentData(entity, new PhysicsDamping { Linear = rigidbody.drag, Angular = rigidbody.angularDrag }); } } // Kinematic. else { DstEntityManager.AddOrSetComponent(entity, PhysicsMass.CreateKinematic(massProperties)); } } // Create any colliders associated with this rigidbody entity. m_ColliderConversionSystem.CreateCollider(entity); }); }