protected override void OnUpdate() { // Make sure last frame's physics jobs are complete before any new ones start m_InputDependencyToComplete.Complete(); float timeStep = Time.DeltaTime; // Tweak if you want a different simulation for this world PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } #region Build World Dependency = PhysicsWorldBuilder.SchedulePhysicsWorldBuild(this, ref PhysicsData, Dependency, timeStep, stepComponent.MultiThreaded > 0, stepComponent.Gravity, LastSystemVersion); #endregion #region Step World // Early-out to prevent simulation context creation in stepper, generally not required if (PhysicsData.PhysicsWorld.NumBodies <= 1) { return; } var stepInput = new SimulationStepInput() { World = PhysicsData.PhysicsWorld, TimeStep = timeStep, Gravity = stepComponent.Gravity, SynchronizeCollisionWorld = false, NumSolverIterations = stepComponent.SolverIterationCount, SolverStabilizationHeuristicSettings = stepComponent.SolverStabilizationHeuristicSettings, HaveStaticBodiesChanged = PhysicsData.HaveStaticBodiesChanged, }; m_Stepper.ScheduleSimulationStepJobs(stepComponent.SimulationType, WorldFilter.Value, stepInput, Dependency, stepComponent.MultiThreaded > 0); // Include the final simulation handle // (Not FinalJobHandle since other systems shouldn't need to depend on the dispose jobs) Dependency = JobHandle.CombineDependencies(Dependency, m_Stepper.FinalSimulationJobHandle); #endregion #region Export World Dependency = PhysicsWorldExporter.SchedulePhysicsWorldExport(this, in PhysicsData.PhysicsWorld, Dependency, PhysicsData.DynamicEntityGroup); #endregion // Just to make sure current server step jobs are complete before next step starts m_InputDependencyToComplete = Dependency; }
protected override void OnUpdate() { // Combine implicit input dependency with the user one var handle = JobHandle.CombineDependencies(Dependency, m_InputDependency); PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } // Swap the simulation implementation if the requested type changed if (Simulation.Type != stepComponent.SimulationType) { Simulation.Dispose(); Simulation = m_SimulationCreators[(int)stepComponent.SimulationType](); } #if !UNITY_DOTSPLAYER float timeStep = UnityEngine.Time.fixedDeltaTime; #else float timeStep = Time.DeltaTime; #endif // Schedule the simulation jobs Simulation.ScheduleStepJobs(new SimulationStepInput() { World = m_BuildPhysicsWorldSystem.PhysicsWorld, TimeStep = timeStep, Gravity = stepComponent.Gravity, SynchronizeCollisionWorld = stepComponent.SynchronizeCollisionWorld > 0, NumSolverIterations = stepComponent.SolverIterationCount, SolverStabilizationHeuristicSettings = stepComponent.SolverStabilizationHeuristicSettings }, m_Callbacks, handle, stepComponent.ThreadCountHint); // Clear the callbacks. User must enqueue them again before the next step. m_Callbacks.Clear(); // Return the final simulation handle // (Not FinalJobHandle since other systems shouldn't need to depend on the dispose jobs) m_OutputDependency = FinalSimulationJobHandle; // Combine implicit output dependency with user one Dependency = JobHandle.CombineDependencies(m_OutputDependency, Dependency); // Inform next systems in the pipeline of their dependency m_ExportPhysicsWorldSystem.AddInputDependency(m_OutputDependency); m_EndFramePhysicsSystem.AddInputDependency(Simulation.FinalJobHandle); // Invalidate input dependency since it's been used now m_InputDependency = default; }
void SetSimulationType(SimulationType simulationType, Scene scene, LoadSceneMode mode) { var entityManager = World.Active.EntityManager; var entities = entityManager.GetAllEntities(); foreach (var entity in entities) { if (entityManager.HasComponent <PhysicsStep>(entity)) { PhysicsStep componentData = entityManager.GetComponentData <PhysicsStep>(entity); componentData.SimulationType = simulationType; entityManager.SetComponentData <PhysicsStep>(entity, componentData); break; } } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var handle = JobHandle.CombineDependencies(m_BuildPhysicsWorldSystem.FinalJobHandle, inputDeps); PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } // Swap the simulation implementation if the requested type changed if (Simulation.Type != stepComponent.SimulationType) { Simulation.Dispose(); Simulation = m_SimulationCreators[(int)stepComponent.SimulationType](); } #if !UNITY_DOTSPLAYER float timeStep = UnityEngine.Time.fixedDeltaTime; #else float timeStep = Time.DeltaTime; #endif // Schedule the simulation jobs var stepInput = new SimulationStepInput { World = m_BuildPhysicsWorldSystem.PhysicsWorld, TimeStep = timeStep, ThreadCountHint = stepComponent.ThreadCountHint, Gravity = stepComponent.Gravity, SynchronizeCollisionWorld = false, NumSolverIterations = stepComponent.SolverIterationCount, Callbacks = m_Callbacks }; Simulation.ScheduleStepJobs(stepInput, handle); FinalSimulationJobHandle = Simulation.FinalSimulationJobHandle; FinalJobHandle = Simulation.FinalJobHandle; // Clear the callbacks. User must enqueue them again before the next step. m_Callbacks.Clear(); return(handle); }
void StepWorldXTimes(int stepAmount) { PhysicsStep stepComponent = PhysicsStep.Default; var stepInput = new SimulationStepInput { World = m_BuildPhysicsWorld.PhysicsWorld, TimeStep = Time.DeltaTime, NumSolverIterations = stepComponent.SolverIterationCount, SolverStabilizationHeuristicSettings = stepComponent.SolverStabilizationHeuristicSettings, Gravity = stepComponent.Gravity, SynchronizeCollisionWorld = true }; for (int i = 0; i < stepAmount; i++) { SimulationContext.Reset(stepInput); Debug.Log("Ball position in simulation " + GetBallPosition()); Simulation.StepImmediate(stepInput, ref SimulationContext); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { Random random = new Random(); PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } var job = new RandomMotionJob { gravity = stepComponent.Gravity, deltaTime = UnityEngine.Time.fixedDeltaTime, random = random }; var jobHandle = job.Schedule(this, inputDeps); return(jobHandle); }
protected override void OnUpdate() { // Make sure dependencies are complete, we'll run everything immediately Dependency.Complete(); float timeStep = Time.DeltaTime; // Tweak if you want a different simulation for this world PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } // Build PhysicsWorld immediately PhysicsWorldBuilder.BuildPhysicsWorldImmediate(this, ref PhysicsData, timeStep, stepComponent.Gravity, LastSystemVersion); // Early out if world is static if (PhysicsData.PhysicsWorld.NumDynamicBodies == 0) { return; } // Run simulation on main thread m_Stepper.StepImmediate(stepComponent.SimulationType, ref PhysicsData.PhysicsWorld, new SimulationStepInput() { World = PhysicsData.PhysicsWorld, TimeStep = timeStep, Gravity = stepComponent.Gravity, SynchronizeCollisionWorld = false, NumSolverIterations = 4, SolverStabilizationHeuristicSettings = Solver.StabilizationHeuristicSettings.Default, HaveStaticBodiesChanged = PhysicsData.HaveStaticBodiesChanged }); // Export physics world only (don't copy CollisionWorld) PhysicsWorldExporter.ExportPhysicsWorldImmediate(this, in PhysicsData.PhysicsWorld, PhysicsData.DynamicEntityGroup); }
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 JobHandle OnUpdate(JobHandle inputDeps) { // Make sure last frame's physics jobs are complete m_EndFramePhysicsSystem.FinalJobHandle.Complete(); // Extract types used by initialize jobs var entityType = GetArchetypeChunkEntityType(); var localToWorldType = GetArchetypeChunkComponentType <LocalToWorld>(true); var parentType = GetArchetypeChunkComponentType <Parent>(true); // var positionType = GetArchetypeChunkComponentType<Translation>(true); // var rotationType = GetArchetypeChunkComponentType<Rotation>(true); var transformType = GetArchetypeChunkComponentType <TransformPredictedState>(true); var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>(true); var physicsVelocityType = GetArchetypeChunkComponentType <PhysicsVelocity>(true); var physicsMassType = GetArchetypeChunkComponentType <PhysicsMass>(true); var physicsDampingType = GetArchetypeChunkComponentType <PhysicsDamping>(true); var physicsGravityFactorType = GetArchetypeChunkComponentType <PhysicsGravityFactor>(true); var physicsCustomTagsType = GetArchetypeChunkComponentType <PhysicsCustomTags>(true); // var physicsJointType = GetArchetypeChunkComponentType<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, 0); // 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, TransformType = transformType, PhysicsColliderType = physicsColliderType, ChunkHasChangesOutput = chunksHaveChanges, m_LastSystemVersion = LastSystemVersion }.Schedule(StaticEntityGroup, inputDeps); 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 // if (numJoints > 0) { jobHandles.Add(new Jobs.CreateDefaultStaticRigidBody { NativeBodies = PhysicsWorld.Bodies, BodyIndex = PhysicsWorld.Bodies.Length - 1 }.Schedule(inputDeps)); } // 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, TransformType = transformType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = 0, RigidBodies = PhysicsWorld.Bodies }.Schedule(DynamicEntityGroup, inputDeps)); jobHandles.Add(new Jobs.CreateMotions { // PositionType = positionType, // RotationType = rotationType, TransformType = transformType, PhysicsVelocityType = physicsVelocityType, PhysicsMassType = physicsMassType, PhysicsDampingType = physicsDampingType, PhysicsGravityFactorType = physicsGravityFactorType, MotionDatas = PhysicsWorld.MotionDatas, MotionVelocities = PhysicsWorld.MotionVelocities }.Schedule(DynamicEntityGroup, inputDeps)); } // 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, TransformType = transformType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = numDynamicBodies, RigidBodies = PhysicsWorld.Bodies }.Schedule(StaticEntityGroup, inputDeps)); } var handle = JobHandle.CombineDependencies(jobHandles); jobHandles.Clear(); // Build joints //if (numJoints > 0) //{ // jobHandles.Add(new Jobs.CreateJoints // { // 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)); FinalJobHandle = JobHandle.CombineDependencies(jobHandles); FinalJobHandle.Complete(); } return(JobHandle.CombineDependencies(FinalJobHandle, inputDeps)); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { // Make sure last frame's physics jobs are complete m_EndFramePhysicsSystem.FinalJobHandle.Complete(); // Extract types used by initialize jobs var entityType = GetArchetypeChunkEntityType(); var positionType = GetArchetypeChunkComponentType <Translation>(true); var rotationType = GetArchetypeChunkComponentType <Rotation>(true); var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>(true); var physicsVelocityType = GetArchetypeChunkComponentType <PhysicsVelocity>(true); var physicsMassType = GetArchetypeChunkComponentType <PhysicsMass>(true); var physicsDampingType = GetArchetypeChunkComponentType <PhysicsDamping>(true); var physicsGravityFactorType = GetArchetypeChunkComponentType <PhysicsGravityFactor>(true); var physicsCustomTagsType = GetArchetypeChunkComponentType <PhysicsCustomTags>(true); var physicsJointType = GetArchetypeChunkComponentType <PhysicsJoint>(true); int numDynamicBodies = DynamicEntityGroup.CalculateEntityCount(); int numStaticBodies = StaticEntityGroup.CalculateEntityCount(); int numJoints = JointEntityGroup.CalculateEntityCount(); m_StaticLayerChangeInfo.NumStaticBodies = numStaticBodies + 1; m_StaticLayerChangeInfo.HaveStaticBodiesChanged = 0; if (numStaticBodies != (PhysicsWorld.StaticBodies.Length - 1)) //-1 for fake static body we add { // Quick test if number of bodies changed m_StaticLayerChangeInfo.HaveStaticBodiesChanged = 1; } else { // Make a job to test for changes int numChunks; // There has to be a better way of doing this... using (NativeArray <ArchetypeChunk> chunks = StaticEntityGroup.CreateArchetypeChunkArray(Allocator.TempJob)) { numChunks = chunks.Length; } var chunksHaveChanges = new NativeArray <int>(numChunks, Allocator.TempJob); inputDeps = new Jobs.CheckStaticBodyChangesJob { PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, ChunkHasChangesOutput = chunksHaveChanges, m_LastSystemVersion = LastSystemVersion }.Schedule(StaticEntityGroup, inputDeps); inputDeps = new Jobs.CheckStaticBodyChangesReduceJob { ChunkHasChangesOutput = chunksHaveChanges, HaveStaticBodiesChanged = m_StaticLayerChangeInfo.HaveStaticBodiesChangedArray, NumStaticBodies = m_StaticLayerChangeInfo.NumStaticBodiesArray }.Schedule(inputDeps); } // Resize the world's native arrays PhysicsWorld.Reset( numStaticBodies: numStaticBodies + 1, // +1 for the default static body numDynamicBodies: numDynamicBodies, numJoints: numJoints); using (var jobHandles = new NativeList <JobHandle>(4, Allocator.Temp)) { // 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(inputDeps)); // 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, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = 0, RigidBodies = PhysicsWorld.Bodies }.Schedule(DynamicEntityGroup, inputDeps)); jobHandles.Add(new Jobs.CreateMotions { PositionType = positionType, RotationType = rotationType, PhysicsVelocityType = physicsVelocityType, PhysicsMassType = physicsMassType, PhysicsDampingType = physicsDampingType, PhysicsGravityFactorType = physicsGravityFactorType, MotionDatas = PhysicsWorld.MotionDatas, MotionVelocities = PhysicsWorld.MotionVelocities }.Schedule(DynamicEntityGroup, inputDeps)); } // 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, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomTagsType = physicsCustomTagsType, FirstBodyIndex = numDynamicBodies, RigidBodies = PhysicsWorld.Bodies }.Schedule(StaticEntityGroup, inputDeps)); } var handle = JobHandle.CombineDependencies(jobHandles); jobHandles.Clear(); // Build joints if (numJoints > 0) { jobHandles.Add(new Jobs.CreateJoints { 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>(); } jobHandles.Add(PhysicsWorld.CollisionWorld.Broadphase.ScheduleBuildJobs(ref PhysicsWorld, timeStep, stepComponent.Gravity, stepComponent.ThreadCountHint, ref m_StaticLayerChangeInfo, handle)); FinalJobHandle = JobHandle.CombineDependencies(jobHandles); } return(JobHandle.CombineDependencies(FinalJobHandle, inputDeps)); }
protected override void OnCreate() { base.OnCreate(); Instance = this; UnityEngine.Physics.autoSimulation = false; matPropBlock = new MaterialPropertyBlock(); // setup physics parameters World.GetOrCreateSystem <FixedStepSimulationSystemGroup>().Timestep = (float)(sfloat.One / (sfloat)60.0f); Entity physicsStep = EntityManager.CreateEntity(typeof(PhysicsStep)); PhysicsStep physicsStepParams = PhysicsStep.Default; physicsStepParams.SolverStabilizationHeuristicSettings = new Solver.StabilizationHeuristicSettings { EnableSolverStabilization = true, EnableFrictionVelocities = true, InertiaScalingFactor = (sfloat)0.0f, VelocityClippingFactor = (sfloat)1.0f }; physicsStepParams.SolverIterationCount = 3; physicsStepParams.MultiThreaded = 1; physicsStepParams.Gravity = new float3(sfloat.Zero, (sfloat)(-60.0f), sfloat.Zero); EntityManager.SetComponentData(physicsStep, physicsStepParams); UnityS.Physics.Material material = UnityS.Physics.Material.Default; material.Friction = sfloat.One; PhysicsParams physicsParamsStatic = PhysicsParams.Default; physicsParamsStatic.isDynamic = false; PhysicsParams physicsParamsDynamic = PhysicsParams.Default; physicsParamsDynamic.isDynamic = true; CreateBox(new float3(sfloat.Zero, sfloat.Zero, sfloat.Zero), new float3((sfloat)500.0f, (sfloat)2.0f, (sfloat)500.0f), quaternion.identity, material, physicsParamsStatic); sfloat radius = (sfloat)10.0f; int count = 7; sfloat sfcount = (sfloat)count; int layers = 4; sfloat size = (sfloat)6.0f; sfloat anglePerLayer = (sfloat)0.25f; // set up stacked boxes for (int l = 0; l < layers; l++) { sfloat offsetY = sfloat.One + ((sfloat)l + (sfloat)0.5f) * size; sfloat angleOffset = anglePerLayer * (sfloat)l; for (int i = 0; i < count; i++) { sfloat t = (sfloat)i / sfcount * math.PI * (sfloat)2.0f + angleOffset; math.sincos(t, out sfloat sin, out sfloat cos); float3 pos = new float3(radius * cos, offsetY, radius * sin); CreateBox(pos, new float3(size, size, size), quaternion.AxisAngle(new float3(sfloat.Zero, sfloat.One, sfloat.Zero), -t), material, physicsParamsDynamic); } } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { // Extract types used by initialize jobs var entityType = GetArchetypeChunkEntityType(); var positionType = GetArchetypeChunkComponentType <Translation>(true); var rotationType = GetArchetypeChunkComponentType <Rotation>(true); var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>(true); var physicsVelocityType = GetArchetypeChunkComponentType <PhysicsVelocity>(true); var physicsMassType = GetArchetypeChunkComponentType <PhysicsMass>(true); var physicsDampingType = GetArchetypeChunkComponentType <PhysicsDamping>(true); var physicsGravityFactorType = GetArchetypeChunkComponentType <PhysicsGravityFactor>(true); var physicsCustomDataType = GetArchetypeChunkComponentType <PhysicsCustomData>(true); var physicsJointType = GetArchetypeChunkComponentType <PhysicsJoint>(true); int numDynamicBodies = DynamicEntityGroup.CalculateLength(); int numStaticBodies = StaticEntityGroup.CalculateLength(); int numJoints = JointEntityGroup.CalculateLength(); // Check for static body changes before the reset() bool haveStaticBodiesChanged = false; { // For now, do this before the reset() - otherwise, we need the BuildRigidBodies jobs to finish if (numStaticBodies != (PhysicsWorld.StaticBodies.Length - 1)) //-1 for fake static body we add { // Quick test if number of bodies changed haveStaticBodiesChanged = true; } else { // Make a job to test for changes int numChunks; // There has to be a better way of doing this... { var chunks = StaticEntityGroup.CreateArchetypeChunkArray(Allocator.TempJob); numChunks = chunks.Length; chunks.Dispose(); } var chunksHaveChanges = new NativeArray <int>(numChunks, Allocator.TempJob); var checkStaticChanges = new Jobs.CheckStaticBodyChangesJob { PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, StaticRigidBodies = PhysicsWorld.StaticBodies, ChunkHasChangesOutput = chunksHaveChanges }; checkStaticChanges.Schedule(StaticEntityGroup, inputDeps).Complete(); for (int i = 0; i < numChunks; i++) { haveStaticBodiesChanged |= chunksHaveChanges[i] != 0; } chunksHaveChanges.Dispose(); } } // Resize the world's native arrays PhysicsWorld.Reset( numStaticBodies: numStaticBodies + 1, // +1 for the default static body numDynamicBodies: numDynamicBodies, numJoints: numJoints); var jobHandles = new NativeList <JobHandle>(4, Allocator.Temp); // 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(inputDeps)); // 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, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomDataType = physicsCustomDataType, FirstBodyIndex = 0, RigidBodies = PhysicsWorld.Bodies }.Schedule(DynamicEntityGroup, inputDeps)); jobHandles.Add(new Jobs.CreateMotions { PositionType = positionType, RotationType = rotationType, PhysicsVelocityType = physicsVelocityType, PhysicsMassType = physicsMassType, PhysicsDampingType = physicsDampingType, PhysicsGravityFactorType = physicsGravityFactorType, MotionDatas = PhysicsWorld.MotionDatas, MotionVelocities = PhysicsWorld.MotionVelocities }.Schedule(DynamicEntityGroup, inputDeps)); } // Now, schedule creation of static bodies, with FirstBodyIndex pointing after the dynamic bodies if (numStaticBodies > 0) { jobHandles.Add(new Jobs.CreateRigidBodies { EntityType = entityType, PositionType = positionType, RotationType = rotationType, PhysicsColliderType = physicsColliderType, PhysicsCustomDataType = physicsCustomDataType, FirstBodyIndex = numDynamicBodies, RigidBodies = PhysicsWorld.Bodies }.Schedule(StaticEntityGroup, inputDeps)); } var handle = JobHandle.CombineDependencies(jobHandles); jobHandles.Clear(); // Build joints if (numJoints > 0) { jobHandles.Add(new Jobs.CreateJoints { JointComponentType = physicsJointType, EntityType = entityType, RigidBodies = PhysicsWorld.Bodies, Joints = PhysicsWorld.Joints, DefaultStaticBodyIndex = PhysicsWorld.Bodies.Length - 1 }.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 float timeStep = UnityEngine.Time.fixedDeltaTime; PhysicsStep stepComponent = PhysicsStep.Default; if (HasSingleton <PhysicsStep>()) { stepComponent = GetSingleton <PhysicsStep>(); } jobHandles.Add(PhysicsWorld.CollisionWorld.Broadphase.ScheduleBuildJobs(ref PhysicsWorld, timeStep, stepComponent.ThreadCountHint, haveStaticBodiesChanged, handle)); FinalJobHandle = JobHandle.CombineDependencies(jobHandles); jobHandles.Dispose(); return(JobHandle.CombineDependencies(FinalJobHandle, inputDeps)); }