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 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); }
public void Update() { // +1 for the default static body PhysicsWorld.Reset(m_NumStaticBodies + 1, m_NumDynamicBodies, m_NumJoints); SimulationStepInput input = new SimulationStepInput { World = PhysicsWorld, TimeStep = Time.fixedDeltaTime, NumSolverIterations = PhysicsStep.Default.SolverIterationCount, Gravity = PhysicsStep.Default.Gravity }; int numOfBodies = m_NumDynamicBodies + m_NumStaticBodies; NativeHashMap <int, int> indexMap = new NativeHashMap <int, int>(m_Bodies.Length, Allocator.TempJob); SimulationContext.Reset(ref PhysicsWorld); new SingleThreadedPhysicsSimulationJob { Bodies = m_Bodies, Joints = m_Joints, Input = input, SimulationContext = SimulationContext, IndexMap = indexMap }.Schedule().Complete(); // Map the results to GameObjects for (int i = 0; i < numOfBodies; i++) { if (!m_Bodies[i].IsDynamic) { continue; } m_BodyIndexToGameObjectMapping.TryGetValue(i, out GameObject g); var t = g.GetComponent <Transform>(); t.position = m_Bodies[i].Position; t.rotation = m_Bodies[i].Orientation; } indexMap.Dispose(); }
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); } }
public virtual IEnumerator LoadScenes([ValueSource(nameof(GetScenes))] string scenePath) { // Log scene name in case Unity crashes and test results aren't written out. Debug.Log("Loading " + scenePath); LogAssert.Expect(LogType.Log, "Loading " + scenePath); // Wait for next frame yield return(null); // Number of steps to simulate const int k_StopAfterStep = 100; // Number of worlds to simulate const int k_NumWorlds = 4; // Number of threads in each of the runs (3rd run is single threaded simulation) NativeArray <int> numThreadsPerRun = new NativeArray <int>(k_NumWorlds, Allocator.Persistent); numThreadsPerRun[0] = 8; numThreadsPerRun[1] = 4; numThreadsPerRun[2] = 0; numThreadsPerRun[3] = -1; // Load the scene and wait 2 frames SceneManager.LoadScene(scenePath); yield return(null); yield return(null); var sampler = DefaultWorld.GetOrCreateSystem <BuildPhysicsWorldSampler>(); sampler.BeginSampling(); while (!sampler.FinishedSampling) { yield return(new WaitForSeconds(0.05f)); } var buildPhysicsWorld = DefaultWorld.GetOrCreateSystem <BuildPhysicsWorld>(); var stepComponent = PhysicsStep.Default; if (buildPhysicsWorld.HasSingleton <PhysicsStep>()) { stepComponent = buildPhysicsWorld.GetSingleton <PhysicsStep>(); } // Extract original world and make copies List <PhysicsWorld> physicsWorlds = new List <PhysicsWorld>(k_NumWorlds); physicsWorlds.Add(sampler.PhysicsWorld.Clone()); physicsWorlds.Add(physicsWorlds[0].Clone()); physicsWorlds.Add(physicsWorlds[1].Clone()); physicsWorlds.Add(physicsWorlds[2].Clone()); NativeArray <int> buildStaticTree = new NativeArray <int>(1, Allocator.Persistent); buildStaticTree[0] = 1; // Simulation step input var stepInput = new SimulationStepInput() { Gravity = stepComponent.Gravity, NumSolverIterations = stepComponent.SolverIterationCount, SynchronizeCollisionWorld = true, TimeStep = Time.fixedDeltaTime }; // Step the simulation on all worlds for (int i = 0; i < physicsWorlds.Count; i++) { int threadCountHint = numThreadsPerRun[i]; if (threadCountHint == -1) { stepInput.World = physicsWorlds[i]; stepInput.World.CollisionWorld.BuildBroadphase( ref stepInput.World, stepInput.TimeStep, stepInput.Gravity, true); #if HAVOK_PHYSICS_EXISTS if (SimulateHavok) { var simulationContext = new Havok.Physics.SimulationContext(Havok.Physics.HavokConfiguration.Default); for (int step = 0; step < k_StopAfterStep; step++) { simulationContext.Reset(ref stepInput.World); new StepHavokJob { Input = stepInput, SimulationContext = simulationContext }.Schedule().Complete(); } simulationContext.Dispose(); } else #endif { var simulationContext = new SimulationContext(); for (int step = 0; step < k_StopAfterStep; step++) { simulationContext.Reset(ref stepInput.World); new StepJob { Input = stepInput, SimulationContext = simulationContext }.Schedule().Complete(); } simulationContext.Dispose(); } } else { #if HAVOK_PHYSICS_EXISTS if (SimulateHavok) { var simulation = new Havok.Physics.HavokSimulation(Havok.Physics.HavokConfiguration.Default); stepInput.World = physicsWorlds[i]; stepInput.World.CollisionWorld.ScheduleBuildBroadphaseJobs( ref stepInput.World, stepInput.TimeStep, stepInput.Gravity, buildStaticTree, default, threadCountHint).Complete();
internal static void CreateRigidBodiesAndMotions(SimulationStepInput input, NativeList <BodyInfo> bodies, NativeHashMap <int, int> indexMap) { NativeArray <RigidBody> dynamicBodies = input.World.DynamicBodies; NativeArray <RigidBody> staticBodies = input.World.StaticBodies; NativeArray <MotionData> motionDatas = input.World.MotionDatas; NativeArray <MotionVelocity> motionVelocities = input.World.MotionVelocities; int dynamicBodyIndex = 0; int staticBodyIndex = 0; for (int i = 0; i < bodies.Length; i++) { BodyInfo bodyInfo = bodies[i]; unsafe { Unity.Physics.Collider *collider = (Unity.Physics.Collider *)bodyInfo.Collider.GetUnsafePtr(); if (bodyInfo.IsDynamic) { dynamicBodies[dynamicBodyIndex] = new RigidBody { WorldFromBody = new RigidTransform(bodyInfo.Orientation, bodyInfo.Position), Collider = bodyInfo.Collider, Entity = Entity.Null, CustomTags = 0 }; motionDatas[dynamicBodyIndex] = new MotionData { WorldFromMotion = new RigidTransform( math.mul(bodyInfo.Orientation, collider->MassProperties.MassDistribution.Transform.rot), math.rotate(bodyInfo.Orientation, collider->MassProperties.MassDistribution.Transform.pos) + bodyInfo.Position ), BodyFromMotion = new RigidTransform(collider->MassProperties.MassDistribution.Transform.rot, collider->MassProperties.MassDistribution.Transform.pos), LinearDamping = 0.0f, AngularDamping = 0.0f }; motionVelocities[dynamicBodyIndex] = new MotionVelocity { LinearVelocity = bodyInfo.LinearVelocity, AngularVelocity = bodyInfo.AngularVelocity, InverseInertia = math.rcp(collider->MassProperties.MassDistribution.InertiaTensor * bodyInfo.Mass), InverseMass = math.rcp(bodyInfo.Mass), AngularExpansionFactor = collider->MassProperties.AngularExpansionFactor, GravityFactor = 1.0f }; indexMap.Add(i, dynamicBodyIndex); dynamicBodyIndex++; } else { staticBodies[staticBodyIndex] = new RigidBody { WorldFromBody = new RigidTransform(bodyInfo.Orientation, bodyInfo.Position), Collider = bodyInfo.Collider, Entity = Entity.Null, CustomTags = 0 }; staticBodyIndex++; } } } // Create default static body unsafe { staticBodies[staticBodyIndex] = new RigidBody { WorldFromBody = new RigidTransform(quaternion.identity, float3.zero), Collider = default,
public static void StepImmediate(SimulationStepInput input, ref SimulationContext simulationContext) { ref PhysicsWorld world = ref input.World;
public SimulationJobHandles ScheduleStepJobs(SimulationStepInput input, SimulationCallbacks callbacks, JobHandle inputDeps, int threadCountHint = 0) => new SimulationJobHandles(inputDeps);
public void Step(SimulationStepInput input) { }
public void Update() { // +1 default static body var NumStaticBodies = (m_BodyInfos.Length - m_NumDynamicBodies) + 1; PhysicsWorld.Reset(NumStaticBodies, m_NumDynamicBodies, m_JointInfos.Length); SimulationStepInput input = new SimulationStepInput { World = PhysicsWorld, TimeStep = World.DefaultGameObjectInjectionWorld.GetExistingSystem <FixedStepSimulationSystemGroup>().Timestep, NumSolverIterations = PhysicsStep.Default.SolverIterationCount, SolverStabilizationHeuristicSettings = PhysicsStep.Default.SolverStabilizationHeuristicSettings, Gravity = PhysicsStep.Default.Gravity }; int numOfBodies = m_NumDynamicBodies + NumStaticBodies; using (var indexMap = new NativeHashMap <int, int>(m_BodyInfos.Length, Allocator.TempJob)) { #if HAVOK_PHYSICS_EXISTS if (SimulateHavok) { HavokSimulationContext.Reset(ref PhysicsWorld); new SingleThreadedPhysicsHavokSimulationJob { Bodies = m_BodyInfos, Joints = m_JointInfos, Input = input, SimulationContext = HavokSimulationContext, BodyInfoToBodiesIndexMap = indexMap }.Run(); } else #endif { SimulationContext.Reset(input); new SingleThreadedPhysicsSimulationJob { BodyInfos = m_BodyInfos, JointInfos = m_JointInfos, Input = input, SimulationContext = SimulationContext, BodyInfoToBodiesIndexMap = indexMap }.Run(); } } // Map the results to GameObjects for (int i = 0; i < m_BodyInfos.Length; i++) { if (!m_BodyInfos[i].IsDynamic) { continue; } m_BodyInfoIndexToGameObjectMapping.TryGetValue(i, out GameObject g); g.transform.position = m_BodyInfos[i].Position; g.transform.rotation = m_BodyInfos[i].Orientation; } }
void ISimulation.ScheduleStepJobs(SimulationStepInput input, JobHandle inputDeps, out JobHandle finalSimulationJobHandle, out JobHandle finalJobHandle) => throw new NotImplementedException();
public void ScheduleStepJobs(SimulationStepInput input, JobHandle inputDeps) { }
public void ScheduleStepJobs(SimulationStepInput input, JobHandle inputDeps, out JobHandle finalSimulationJobHandle, out JobHandle finalJobHandle) { finalSimulationJobHandle = new JobHandle(); finalJobHandle = new JobHandle(); }
public SimulationJobHandles ScheduleStepJobs(SimulationStepInput input, SimulationCallbacks callbacks, JobHandle inputDeps, bool multiThreaded = true) => new SimulationJobHandles(inputDeps);