diff --git a/Engine.Physics2D/Abstract/IPhysicsEngine2D.cs b/Engine.Physics2D/Abstract/IPhysicsEngine2D.cs index 903bb9e..c65f139 100644 --- a/Engine.Physics2D/Abstract/IPhysicsEngine2D.cs +++ b/Engine.Physics2D/Abstract/IPhysicsEngine2D.cs @@ -26,6 +26,13 @@ public interface IPhysicsEngine2D /// The time step. void Step(float deltaTime); + /// + /// Advances the physics simulation by the specified time on a single . + /// + /// The to be progressed individually. + /// The time step. + void StepIndividual(IRigidBody2D rigidBody, float deltaTime); + delegate void PhysicsIterationEventHandler(IPhysicsEngine2D sender, float iterationDeltaTime); delegate void PhysicsStepEventHandler(IPhysicsEngine2D sender, float stepDeltaTime); } diff --git a/Engine.Physics2D/PhysicsEngine2D.cs b/Engine.Physics2D/PhysicsEngine2D.cs index 992592f..7756a5e 100644 --- a/Engine.Physics2D/PhysicsEngine2D.cs +++ b/Engine.Physics2D/PhysicsEngine2D.cs @@ -58,43 +58,7 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D if (!colliderY.IsActive) continue; - if (colliderX.RigidBody2D == colliderY.RigidBody2D) - continue; - - bool bothCollidersAreTriggers = colliderX.IsTrigger && colliderX.IsTrigger == colliderY.IsTrigger; - if (bothCollidersAreTriggers) - continue; - - bool bothCollidersAreStatic = (colliderX.RigidBody2D?.IsStatic ?? true) && (colliderY.RigidBody2D?.IsStatic ?? true); - if (bothCollidersAreStatic) - continue; - - if (collisionDetector.TryDetect(colliderX, colliderY, out CollisionDetectionInformation information)) - { - if (colliderX.IsTrigger) - { - colliderX.Trigger(colliderY); - continue; - } - else if (colliderY.IsTrigger) - { - colliderY.Trigger(colliderX); - continue; - } - - if (information.Detector == colliderX) - { - colliderX.Detect(information); - colliderY.Detect(information.Reverse()); - } - else - { - colliderX.Detect(information.Reverse()); - colliderY.Detect(information); - } - - collisionResolver?.Resolve(information); - } + ResolveColliders(colliderX, colliderY); } } @@ -107,6 +71,96 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D OnPhysicsStep?.InvokeSafe(this, deltaTime); } + public void StepIndividual(IRigidBody2D rigidBody, float deltaTime) + { + float intervalDeltaTime = deltaTime / IterationPerStep; + + System.Collections.Generic.List childColliders = []; + System.Collections.Generic.List physicsPreUpdates = []; + System.Collections.Generic.List physicsUpdates = []; + System.Collections.Generic.List physicsPostUpdates = []; + + rigidBody.BehaviourController.GetBehavioursInChildren(childColliders); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsPreUpdates); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsUpdates); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsPostUpdates); + + foreach (IPrePhysicsUpdate physicsPreUpdate in physicsPreUpdates) + physicsPreUpdate.PrePhysicsUpdate(deltaTime); + + foreach (IPhysicsUpdate physicsUpdate in physicsUpdates) + physicsUpdate.PhysicsUpdate(deltaTime); + + for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++) + { + StepRigidBody(rigidBody, intervalDeltaTime); + + foreach (ICollider2D collider in childColliders) + collider.Recalculate(); + + for (int x = 0; x < childColliders.Count; x++) + { + ICollider2D? colliderX = childColliders[x]; + if (!colliderX.IsActive) + continue; + + for (int y = 0; y < colliderCollector.Behaviours.Count; y++) + { + ICollider2D? colliderY = colliderCollector.Behaviours[y]; + + if (!colliderY.IsActive) + continue; + + ResolveColliders(colliderX, colliderY); + } + } + } + + foreach (IPostPhysicsUpdate physicsPostUpdate in physicsPostUpdates) + physicsPostUpdate.PostPhysicsUpdate(deltaTime); + } + + private void ResolveColliders(ICollider2D colliderX, ICollider2D colliderY) + { + if (colliderX.RigidBody2D == colliderY.RigidBody2D) + return; + + bool bothCollidersAreTriggers = colliderX.IsTrigger && colliderX.IsTrigger == colliderY.IsTrigger; + if (bothCollidersAreTriggers) + return; + + bool bothCollidersAreStatic = (colliderX.RigidBody2D?.IsStatic ?? true) && (colliderY.RigidBody2D?.IsStatic ?? true); + if (bothCollidersAreStatic) + return; + + if (!collisionDetector.TryDetect(colliderX, colliderY, out CollisionDetectionInformation information)) + return; + + if (colliderX.IsTrigger) + { + colliderX.Trigger(colliderY); + return; + } + else if (colliderY.IsTrigger) + { + colliderY.Trigger(colliderX); + return; + } + + if (information.Detector == colliderX) + { + colliderX.Detect(information); + colliderY.Detect(information.Reverse()); + } + else + { + colliderX.Detect(information.Reverse()); + colliderY.Detect(information); + } + + collisionResolver?.Resolve(information); + } + private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime) { if (rigidBody.IsStatic || !rigidBody.IsActive) diff --git a/Engine.Physics2D/PhysicsEngine2DStandalone.cs b/Engine.Physics2D/PhysicsEngine2DStandalone.cs index d4bbc7f..ef307be 100644 --- a/Engine.Physics2D/PhysicsEngine2DStandalone.cs +++ b/Engine.Physics2D/PhysicsEngine2DStandalone.cs @@ -62,47 +62,10 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D for (int y = x + 1; y < colliders.Count; y++) { ICollider2D? colliderY = colliders[y]; - if (!colliderY.IsActive) - continue; + return; - if (colliderX.RigidBody2D == colliderY.RigidBody2D) - continue; - - bool bothCollidersAreTriggers = colliderX.IsTrigger && colliderX.IsTrigger == colliderY.IsTrigger; - if (bothCollidersAreTriggers) - continue; - - bool bothCollidersAreStatic = (colliderX.RigidBody2D?.IsStatic ?? true) && (colliderY.RigidBody2D?.IsStatic ?? true); - if (bothCollidersAreStatic) - continue; - - if (collisionDetector.TryDetect(colliderX, colliderY, out CollisionDetectionInformation information)) - { - if (colliderX.IsTrigger) - { - colliderX.Trigger(colliderY); - continue; - } - else if (colliderY.IsTrigger) - { - colliderY.Trigger(colliderX); - continue; - } - - if (information.Detector == colliderX) - { - colliderX.Detect(information); - colliderY.Detect(information.Reverse()); - } - else - { - colliderX.Detect(information.Reverse()); - colliderY.Detect(information); - } - - collisionResolver?.Resolve(information); - } + ResolveColliders(colliderX, colliderY); } } OnPhysicsIteration?.InvokeSafe(this, intervalDeltaTime); @@ -110,6 +73,96 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D OnPhysicsStep?.InvokeSafe(this, deltaTime); } + public void StepIndividual(IRigidBody2D rigidBody, float deltaTime) + { + float intervalDeltaTime = deltaTime / IterationPerStep; + + List childColliders = []; + List physicsPreUpdates = []; + List physicsUpdates = []; + List physicsPostUpdates = []; + + rigidBody.BehaviourController.GetBehavioursInChildren(childColliders); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsPreUpdates); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsUpdates); + rigidBody.BehaviourController.GetBehavioursInChildren(physicsPostUpdates); + + foreach (IPrePhysicsUpdate physicsPreUpdate in physicsPreUpdates) + physicsPreUpdate.PrePhysicsUpdate(deltaTime); + + foreach (IPhysicsUpdate physicsUpdate in physicsUpdates) + physicsUpdate.PhysicsUpdate(deltaTime); + + for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++) + { + StepRigidBody(rigidBody, intervalDeltaTime); + + foreach (ICollider2D collider in childColliders) + collider.Recalculate(); + + for (int x = 0; x < childColliders.Count; x++) + { + ICollider2D? colliderX = childColliders[x]; + if (!colliderX.IsActive) + continue; + + for (int y = 0; y < colliders.Count; y++) + { + ICollider2D? colliderY = colliders[y]; + + if (!colliderY.IsActive) + continue; + + ResolveColliders(colliderX, colliderY); + } + } + } + + foreach (IPostPhysicsUpdate physicsPostUpdate in physicsPostUpdates) + physicsPostUpdate.PostPhysicsUpdate(deltaTime); + } + + private void ResolveColliders(ICollider2D colliderX, ICollider2D colliderY) + { + if (colliderX.RigidBody2D == colliderY.RigidBody2D) + return; + + bool bothCollidersAreTriggers = colliderX.IsTrigger && colliderX.IsTrigger == colliderY.IsTrigger; + if (bothCollidersAreTriggers) + return; + + bool bothCollidersAreStatic = (colliderX.RigidBody2D?.IsStatic ?? true) && (colliderY.RigidBody2D?.IsStatic ?? true); + if (bothCollidersAreStatic) + return; + + if (!collisionDetector.TryDetect(colliderX, colliderY, out CollisionDetectionInformation information)) + return; + + if (colliderX.IsTrigger) + { + colliderX.Trigger(colliderY); + return; + } + else if (colliderY.IsTrigger) + { + colliderY.Trigger(colliderX); + return; + } + + if (information.Detector == colliderX) + { + colliderX.Detect(information); + colliderY.Detect(information.Reverse()); + } + else + { + colliderX.Detect(information.Reverse()); + colliderY.Detect(information); + } + + collisionResolver?.Resolve(information); + } + private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime) { if (rigidBody.IsStatic || !rigidBody.IsActive)