protected override void OnUpdate() { // Make sure last frame's physics jobs are complete before any new ones start m_InputDependencyToComplete.Complete(); // Combine implicit input dependency with the user one Dependency = JobHandle.CombineDependencies(Dependency, m_InputDependency); int numDynamicBodies = DynamicEntityGroup.CalculateEntityCount(); int numStaticBodies = StaticEntityGroup.CalculateEntityCount(); int numJoints = JointEntityGroup.CalculateEntityCount(); int previousStaticBodyCount = PhysicsWorld.NumStaticBodies; // Resize the world's native arrays PhysicsWorld.Reset( numStaticBodies + 1, // +1 for the default static body numDynamicBodies, numJoints); if (PhysicsWorld.NumBodies == 0) { // If the static body count has changed, make sure to set the correct value to HaveStaticBodiesChanged if (PhysicsWorld.NumStaticBodies != previousStaticBodyCount) { HaveStaticBodiesChanged[0] = 1; } else { HaveStaticBodiesChanged[0] = 0; } m_OutputDependency = Dependency; ChainDependencies(); // No bodies in the scene, no need to do anything else return; } // Extract types used by initialize jobs var entityType = GetEntityTypeHandle(); var localToWorldType = GetComponentTypeHandle <LocalToWorld>(true); var parentType = GetComponentTypeHandle <Parent>(true); var positionType = GetComponentTypeHandle <Translation>(true); var rotationType = GetComponentTypeHandle <Rotation>(true); var physicsColliderType = GetComponentTypeHandle <PhysicsCollider>(true); var physicsVelocityType = GetComponentTypeHandle <PhysicsVelocity>(true); var physicsMassType = GetComponentTypeHandle <PhysicsMass>(true); var physicsMassOverrideType = GetComponentTypeHandle <PhysicsMassOverride>(true); var physicsDampingType = GetComponentTypeHandle <PhysicsDamping>(true); var physicsGravityFactorType = GetComponentTypeHandle <PhysicsGravityFactor>(true); var physicsCustomTagsType = GetComponentTypeHandle <PhysicsCustomTags>(true); var physicsConstrainedBodyPairType = GetComponentTypeHandle <PhysicsConstrainedBodyPair>(true); var physicsJointType = GetComponentTypeHandle <PhysicsJoint>(true); // Determine if the static bodies have changed in any way that will require the static broadphase tree to be rebuilt JobHandle staticBodiesCheckHandle = default; HaveStaticBodiesChanged[0] = 0; { if (PhysicsWorld.NumStaticBodies != previousStaticBodyCount) { HaveStaticBodiesChanged[0] = 1; } else { staticBodiesCheckHandle = new Jobs.CheckStaticBodyChangesJob { LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, m_LastSystemVersion = LastSystemVersion, Result = HaveStaticBodiesChanged }.ScheduleParallel(StaticEntityGroup, 1, Dependency); } } using (var jobHandles = new NativeList <JobHandle>(4, Allocator.Temp)) { // Static body changes check jobs jobHandles.Add(staticBodiesCheckHandle); // Create the default static body at the end of the body list // TODO: could skip this if no joints present jobHandles.Add(new Jobs.CreateDefaultStaticRigidBody { NativeBodies = PhysicsWorld.Bodies, BodyIndex = PhysicsWorld.Bodies.Length - 1, EntityBodyIndexMap = PhysicsWorld.CollisionWorld.EntityBodyIndexMap.AsParallelWriter(), }.Schedule(Dependency)); // Dynamic bodies. // Create these separately from static bodies to maintain a 1:1 mapping // between dynamic bodies and their motions. if (numDynamicBodies > 0) { jobHandles.Add(new Jobs.CreateRigidBodies { EntityType = entityType, LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = 0, RigidBodies = PhysicsWorld.Bodies, EntityBodyIndexMap = PhysicsWorld.CollisionWorld.EntityBodyIndexMap.AsParallelWriter(), }.ScheduleParallel(DynamicEntityGroup, 1, Dependency)); jobHandles.Add(new Jobs.CreateMotions { PositionType = positionType, RotationType = rotationType, PhysicsVelocityType = physicsVelocityType, PhysicsMassType = physicsMassType, PhysicsMassOverrideType = physicsMassOverrideType, PhysicsDampingType = physicsDampingType, PhysicsGravityFactorType = physicsGravityFactorType, MotionDatas = PhysicsWorld.MotionDatas, MotionVelocities = PhysicsWorld.MotionVelocities }.ScheduleParallel(DynamicEntityGroup, 1, Dependency)); } // Now, schedule creation of static bodies, with FirstBodyIndex pointing after // the dynamic and kinematic bodies if (numStaticBodies > 0) { jobHandles.Add(new Jobs.CreateRigidBodies { EntityType = entityType, LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = numDynamicBodies, RigidBodies = PhysicsWorld.Bodies, EntityBodyIndexMap = PhysicsWorld.CollisionWorld.EntityBodyIndexMap.AsParallelWriter(), }.ScheduleParallel(StaticEntityGroup, 1, Dependency)); } var handle = JobHandle.CombineDependencies(jobHandles); jobHandles.Clear(); // Build joints if (numJoints > 0) { jobHandles.Add(new Jobs.CreateJoints { ConstrainedBodyPairComponentType = physicsConstrainedBodyPairType, JointComponentType = physicsJointType, EntityType = entityType, RigidBodies = PhysicsWorld.Bodies, Joints = PhysicsWorld.Joints, DefaultStaticBodyIndex = PhysicsWorld.Bodies.Length - 1, NumDynamicBodies = numDynamicBodies, EntityBodyIndexMap = PhysicsWorld.CollisionWorld.EntityBodyIndexMap, EntityJointIndexMap = PhysicsWorld.DynamicsWorld.EntityJointIndexMap.AsParallelWriter(), }.ScheduleParallel(JointEntityGroup, 1, handle)); } // Build the broadphase // TODO: could optimize this by gathering the AABBs and filters at the same time as building the bodies above sfloat timeStep = (sfloat)Time.DeltaTime; PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } JobHandle buildBroadphaseHandle = PhysicsWorld.CollisionWorld.ScheduleBuildBroadphaseJobs( ref PhysicsWorld, timeStep, stepComponent.Gravity, HaveStaticBodiesChanged, handle, stepComponent.MultiThreaded > 0); jobHandles.Add(buildBroadphaseHandle); m_OutputDependency = JobHandle.CombineDependencies(jobHandles); } #if ENABLE_UNITY_COLLECTIONS_CHECKS RecordIntegrity(IntegrityCheckMap); #endif ChainDependencies(); }
protected override void OnUpdate() { // Make sure last frame's physics jobs are complete before any new ones start m_EndFramePhysicsSystem.GetOutputDependency().Complete(); // Combine implicit input dependency with the user one Dependency = JobHandle.CombineDependencies(Dependency, m_InputDependency); // Extract types used by initialize jobs var entityType = GetEntityTypeHandle(); var localToWorldType = GetComponentTypeHandle <LocalToWorld>(true); var parentType = GetComponentTypeHandle <Parent>(true); var positionType = GetComponentTypeHandle <Translation>(true); var rotationType = GetComponentTypeHandle <Rotation>(true); var physicsColliderType = GetComponentTypeHandle <PhysicsCollider>(true); var physicsVelocityType = GetComponentTypeHandle <PhysicsVelocity>(true); var physicsMassType = GetComponentTypeHandle <PhysicsMass>(true); var physicsMassOverrideType = GetComponentTypeHandle <PhysicsMassOverride>(true); var physicsDampingType = GetComponentTypeHandle <PhysicsDamping>(true); var physicsGravityFactorType = GetComponentTypeHandle <PhysicsGravityFactor>(true); var physicsCustomTagsType = GetComponentTypeHandle <PhysicsCustomTags>(true); var physicsConstrainedBodyPairType = GetComponentTypeHandle <PhysicsConstrainedBodyPair>(true); var physicsJointType = GetComponentTypeHandle <PhysicsJoint>(true); int numDynamicBodies = DynamicEntityGroup.CalculateEntityCount(); int numStaticBodies = StaticEntityGroup.CalculateEntityCount(); int numJoints = JointEntityGroup.CalculateEntityCount(); int previousStaticBodyCount = PhysicsWorld.NumStaticBodies; // Resize the world's native arrays PhysicsWorld.Reset( numStaticBodies + 1, // +1 for the default static body numDynamicBodies, numJoints); // Determine if the static bodies have changed in any way that will require the static broadphase tree to be rebuilt JobHandle staticBodiesCheckHandle = default; var haveStaticBodiesChanged = new NativeArray <int>(1, Allocator.TempJob); haveStaticBodiesChanged[0] = 0; { if (PhysicsWorld.NumStaticBodies != previousStaticBodyCount) { haveStaticBodiesChanged[0] = 1; } else { // Make a job to test for changes int numChunks; using (NativeArray <ArchetypeChunk> chunks = StaticEntityGroup.CreateArchetypeChunkArray(Allocator.TempJob)) { numChunks = chunks.Length; } var chunksHaveChanges = new NativeArray <int>(numChunks, Allocator.TempJob); staticBodiesCheckHandle = new Jobs.CheckStaticBodyChangesJob { LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, ChunkHasChangesOutput = chunksHaveChanges, m_LastSystemVersion = LastSystemVersion }.Schedule(StaticEntityGroup, Dependency); staticBodiesCheckHandle = new Jobs.CheckStaticBodyChangesReduceJob { ChunkHasChangesOutput = chunksHaveChanges, Result = haveStaticBodiesChanged }.Schedule(staticBodiesCheckHandle); } } using (var jobHandles = new NativeList <JobHandle>(4, Allocator.Temp)) { // Static body changes check jobs jobHandles.Add(staticBodiesCheckHandle); // Create the default static body at the end of the body list // TODO: could skip this if no joints present jobHandles.Add(new Jobs.CreateDefaultStaticRigidBody { NativeBodies = PhysicsWorld.Bodies, BodyIndex = PhysicsWorld.Bodies.Length - 1 }.Schedule(Dependency)); // Dynamic bodies. // Create these separately from static bodies to maintain a 1:1 mapping // between dynamic bodies and their motions. if (numDynamicBodies > 0) { jobHandles.Add(new Jobs.CreateRigidBodies { EntityType = entityType, LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = 0, RigidBodies = PhysicsWorld.Bodies }.Schedule(DynamicEntityGroup, Dependency)); jobHandles.Add(new Jobs.CreateMotions { PositionType = positionType, RotationType = rotationType, PhysicsVelocityType = physicsVelocityType, PhysicsMassType = physicsMassType, PhysicsMassOverrideType = physicsMassOverrideType, PhysicsDampingType = physicsDampingType, PhysicsGravityFactorType = physicsGravityFactorType, MotionDatas = PhysicsWorld.MotionDatas, MotionVelocities = PhysicsWorld.MotionVelocities }.Schedule(DynamicEntityGroup, Dependency)); } // Now, schedule creation of static bodies, with FirstBodyIndex pointing after // the dynamic and kinematic bodies if (numStaticBodies > 0) { jobHandles.Add(new Jobs.CreateRigidBodies { EntityType = entityType, LocalToWorldType = localToWorldType, ParentType = parentType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = numDynamicBodies, RigidBodies = PhysicsWorld.Bodies }.Schedule(StaticEntityGroup, Dependency)); } var handle = JobHandle.CombineDependencies(jobHandles); jobHandles.Clear(); // Build joints if (numJoints > 0) { jobHandles.Add(new Jobs.CreateJoints { ConstrainedBodyPairComponentType = physicsConstrainedBodyPairType, JointComponentType = physicsJointType, EntityType = entityType, RigidBodies = PhysicsWorld.Bodies, Joints = PhysicsWorld.Joints, DefaultStaticBodyIndex = PhysicsWorld.Bodies.Length - 1, NumDynamicBodies = numDynamicBodies }.Schedule(JointEntityGroup, handle)); } // Build the broadphase // TODO: could optimize this by gathering the AABBs and filters at the same time as building the bodies above #if !UNITY_DOTSPLAYER float timeStep = UnityEngine.Time.fixedDeltaTime; #else float timeStep = Time.DeltaTime; #endif PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } JobHandle buildBroadphaseHandle = PhysicsWorld.CollisionWorld.ScheduleBuildBroadphaseJobs( ref PhysicsWorld, timeStep, stepComponent.Gravity, haveStaticBodiesChanged, handle, stepComponent.ThreadCountHint); jobHandles.Add(haveStaticBodiesChanged.Dispose(buildBroadphaseHandle)); m_OutputDependency = JobHandle.CombineDependencies(jobHandles); } // Combine implicit output dependency with user one Dependency = JobHandle.CombineDependencies(m_OutputDependency, Dependency); // Inform next system in the pipeline of its dependency m_StepPhysicsWorldSystem.AddInputDependency(Dependency); // Invalidate input dependency since it's been used by now m_InputDependency = default; }