perf!: events refactored throughout all the project to use Event<> class
All delegate events are refactored to use the Event<TSender> and Event<TSender, TArgument> for performance issues regarding delegate events creating garbage, also this gives us better control on event invocation since C# Delegates did also create unnecessary garbage during Delegate.DynamicInvoke
This commit is contained in:
@@ -10,17 +10,17 @@ public interface ICollider2D : IBehaviour
|
||||
/// <summary>
|
||||
/// Event triggered when a collision is detected.
|
||||
/// </summary>
|
||||
event CollisionDetectedEventHandler? OnCollisionDetected;
|
||||
Event<ICollider2D, CollisionDetectionInformation> OnCollisionDetected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when a collision is resolved.
|
||||
/// </summary>
|
||||
event CollisionResolvedEventHandler? OnCollisionResolved;
|
||||
Event<ICollider2D, CollisionDetectionInformation> OnCollisionResolved { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when another <see cref="ICollider2D"/> triggers this <see cref="ICollider2D"/>.
|
||||
/// </summary>
|
||||
event TriggeredEventHandler? OnTriggered;
|
||||
Event<ICollider2D, ICollider2D> OnTriggered { get; }
|
||||
|
||||
/// <inheritdoc cref="ITransform2D" />
|
||||
ITransform2D Transform { get; }
|
||||
@@ -44,7 +44,7 @@ public interface ICollider2D : IBehaviour
|
||||
void Resolve(CollisionDetectionInformation collisionDetectionInformation);
|
||||
void Trigger(ICollider2D initiator);
|
||||
|
||||
delegate void CollisionDetectedEventHandler(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
|
||||
delegate void CollisionResolvedEventHandler(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
|
||||
delegate void TriggeredEventHandler(ICollider2D sender, ICollider2D initiatorCollider);
|
||||
readonly record struct CollisionDetectedArguments(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
|
||||
readonly record struct CollisionResolvedArguments(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
|
||||
readonly record struct TriggeredArguments(ICollider2D sender, ICollider2D initiatorCollider);
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
namespace Syntriax.Engine.Physics2D;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,12 +10,12 @@ public interface IPhysicsEngine2D
|
||||
/// <summary>
|
||||
/// Event triggered when the <see cref="IPhysicsEngine2D"/> has done a single physics iteration.
|
||||
/// </summary>
|
||||
event PhysicsIterationEventHandler? OnPhysicsIteration;
|
||||
Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when the <see cref="IPhysicsEngine2D"/> has done a full physics step/>.
|
||||
/// </summary>
|
||||
event PhysicsStepEventHandler? OnPhysicsStep;
|
||||
Event<IPhysicsEngine2D, float> OnPhysicsStep { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of iterations the <see cref="IPhysicsEngine2D"/> performs per step.
|
||||
@@ -33,6 +35,6 @@ public interface IPhysicsEngine2D
|
||||
/// <param name="deltaTime">The time step.</param>
|
||||
void StepIndividual(IRigidBody2D rigidBody, float deltaTime);
|
||||
|
||||
delegate void PhysicsIterationEventHandler(IPhysicsEngine2D sender, float iterationDeltaTime);
|
||||
delegate void PhysicsStepEventHandler(IPhysicsEngine2D sender, float stepDeltaTime);
|
||||
readonly record struct PhysicsIterationArguments(IPhysicsEngine2D sender, float iterationDeltaTime);
|
||||
readonly record struct PhysicsStepArguments(IPhysicsEngine2D sender, float stepDeltaTime);
|
||||
}
|
||||
|
@@ -4,13 +4,30 @@ namespace Syntriax.Engine.Physics2D;
|
||||
|
||||
public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
|
||||
{
|
||||
public event ICollider2D.CollisionDetectedEventHandler? OnCollisionDetected = null;
|
||||
public event ICollider2D.CollisionResolvedEventHandler? OnCollisionResolved = null;
|
||||
public event ICollider2D.TriggeredEventHandler? OnTriggered = null;
|
||||
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionDetected { get; } = new();
|
||||
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionResolved { get; } = new();
|
||||
public Event<ICollider2D, ICollider2D> OnTriggered { get; } = new();
|
||||
|
||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAddedToController = null!;
|
||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemovedFromController = null!;
|
||||
private readonly Event<ITransform2D, ITransform2D.PositionChangedArguments>.EventHandler delegateSetNeedsRecalculationFromPosition = null!;
|
||||
private readonly Event<ITransform2D, ITransform2D.RotationChangedArguments>.EventHandler delegateSetNeedsRecalculationFromRotation = null!;
|
||||
private readonly Event<ITransform2D, ITransform2D.ScaleChangedArguments>.EventHandler delegateSetNeedsRecalculationFromScale = null!;
|
||||
private readonly Event<IUniverseObject, IUniverseObject.ParentChangedArguments>.EventHandler delegateUpdateRigidBody2D = null!;
|
||||
|
||||
protected bool NeedsRecalculation { get; set; } = true;
|
||||
protected IRigidBody2D? _rigidBody2D = null;
|
||||
|
||||
protected Collider2DBehaviourBase()
|
||||
{
|
||||
delegateOnBehaviourAddedToController = OnBehaviourAddedToController;
|
||||
delegateOnBehaviourRemovedFromController = OnBehaviourRemovedFromController;
|
||||
delegateSetNeedsRecalculationFromPosition = SetNeedsRecalculationFromPosition;
|
||||
delegateSetNeedsRecalculationFromRotation = SetNeedsRecalculationFromRotation;
|
||||
delegateSetNeedsRecalculationFromScale = SetNeedsRecalculationFromScale;
|
||||
delegateUpdateRigidBody2D = UpdateRigidBody2D;
|
||||
}
|
||||
|
||||
public IRigidBody2D? RigidBody2D => _rigidBody2D;
|
||||
public bool IsTrigger { get; set; } = false;
|
||||
|
||||
@@ -29,44 +46,44 @@ public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
|
||||
{
|
||||
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
|
||||
|
||||
BehaviourController.OnBehaviourAdded += OnBehaviourAddedToController;
|
||||
BehaviourController.OnBehaviourRemoved += OnBehaviourRemovedFromController;
|
||||
BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAddedToController);
|
||||
BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemovedFromController);
|
||||
|
||||
Transform.OnPositionChanged += SetNeedsRecalculationFromPosition;
|
||||
Transform.OnRotationChanged += SetNeedsRecalculationFromRotation;
|
||||
Transform.OnScaleChanged += SetNeedsRecalculationFromScale;
|
||||
UniverseObject.OnParentChanged += UpdateRigidBody2D;
|
||||
Transform.OnPositionChanged.AddListener(delegateSetNeedsRecalculationFromPosition);
|
||||
Transform.OnRotationChanged.AddListener(delegateSetNeedsRecalculationFromRotation);
|
||||
Transform.OnScaleChanged.AddListener(delegateSetNeedsRecalculationFromScale);
|
||||
UniverseObject.OnParentChanged.AddListener(delegateUpdateRigidBody2D);
|
||||
}
|
||||
|
||||
private void UpdateRigidBody2D(IUniverseObject sender, IUniverseObject? previousParent, IUniverseObject? newParent)
|
||||
private void UpdateRigidBody2D(IUniverseObject sender, IUniverseObject.ParentChangedArguments args)
|
||||
{
|
||||
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
|
||||
}
|
||||
|
||||
private void OnBehaviourAddedToController(IBehaviourController _, IBehaviour behaviour)
|
||||
private void OnBehaviourAddedToController(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments args)
|
||||
{
|
||||
if (behaviour is IRigidBody2D rigidBody)
|
||||
if (args.BehaviourAdded is IRigidBody2D rigidBody)
|
||||
_rigidBody2D = rigidBody;
|
||||
}
|
||||
|
||||
private void OnBehaviourRemovedFromController(IBehaviourController _, IBehaviour behaviour)
|
||||
private void OnBehaviourRemovedFromController(IBehaviourController sender, IBehaviourController.BehaviourRemovedArguments args)
|
||||
{
|
||||
if (behaviour is IRigidBody2D _)
|
||||
if (args.BehaviourRemoved is IRigidBody2D)
|
||||
_rigidBody2D = null;
|
||||
}
|
||||
|
||||
private void SetNeedsRecalculationFromScale(ITransform2D sender, Vector2D previousScale) => NeedsRecalculation = true;
|
||||
private void SetNeedsRecalculationFromPosition(ITransform2D sender, Vector2D previousPosition) => NeedsRecalculation = true;
|
||||
private void SetNeedsRecalculationFromRotation(ITransform2D sender, float previousRotation) => NeedsRecalculation = true;
|
||||
private void SetNeedsRecalculationFromPosition(ITransform2D sender, ITransform2D.PositionChangedArguments args) => NeedsRecalculation = true;
|
||||
private void SetNeedsRecalculationFromScale(ITransform2D sender, ITransform2D.ScaleChangedArguments args) => NeedsRecalculation = true;
|
||||
private void SetNeedsRecalculationFromRotation(ITransform2D sender, ITransform2D.RotationChangedArguments args) => NeedsRecalculation = true;
|
||||
|
||||
protected override void OnFinalize()
|
||||
{
|
||||
BehaviourController.OnBehaviourAdded -= OnBehaviourAddedToController;
|
||||
BehaviourController.OnBehaviourRemoved -= OnBehaviourRemovedFromController;
|
||||
Transform.OnScaleChanged -= SetNeedsRecalculationFromScale;
|
||||
BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAddedToController);
|
||||
BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemovedFromController);
|
||||
Transform.OnScaleChanged.RemoveListener(delegateSetNeedsRecalculationFromScale);
|
||||
|
||||
Transform.OnPositionChanged -= SetNeedsRecalculationFromPosition;
|
||||
Transform.OnRotationChanged -= SetNeedsRecalculationFromRotation;
|
||||
Transform.OnPositionChanged.RemoveListener(delegateSetNeedsRecalculationFromPosition);
|
||||
Transform.OnRotationChanged.RemoveListener(delegateSetNeedsRecalculationFromRotation);
|
||||
}
|
||||
|
||||
public void Detect(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionDetected?.Invoke(this, collisionDetectionInformation);
|
||||
|
@@ -7,6 +7,8 @@ namespace Syntriax.Engine.Physics2D;
|
||||
|
||||
public class PhysicsCoroutineManager : UniverseObject
|
||||
{
|
||||
private readonly Event<IUniverse, IUniverse.UpdateArguments>.EventHandler delegateOnUpdate = null!;
|
||||
|
||||
private readonly List<IEnumerator> enumerators = [];
|
||||
private IPhysicsEngine2D? physicsEngine = null;
|
||||
|
||||
@@ -25,9 +27,9 @@ public class PhysicsCoroutineManager : UniverseObject
|
||||
{
|
||||
physicsEngine = universe.GetUniverseObject<IPhysicsEngine2D>();
|
||||
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
||||
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
||||
foundPhysicsEngine.OnPhysicsStep.RemoveListener(OnPhysicsStep);
|
||||
else
|
||||
universe.OnUpdate += OnUpdate;
|
||||
universe.OnUpdate.AddListener(OnUpdate);
|
||||
}
|
||||
|
||||
private void OnPhysicsStep(IPhysicsEngine2D sender, float stepDeltaTime)
|
||||
@@ -45,11 +47,11 @@ public class PhysicsCoroutineManager : UniverseObject
|
||||
protected override void OnExitingUniverse(IUniverse universe)
|
||||
{
|
||||
if (physicsEngine is IPhysicsEngine2D existingPhysicsEngine)
|
||||
existingPhysicsEngine.OnPhysicsStep -= OnPhysicsStep;
|
||||
universe.OnUpdate -= OnUpdate;
|
||||
existingPhysicsEngine.OnPhysicsStep.RemoveListener(OnPhysicsStep);
|
||||
universe.OnUpdate.RemoveListener(OnUpdate);
|
||||
}
|
||||
|
||||
private void OnUpdate(IUniverse sender, UniverseTime engineTime)
|
||||
private void OnUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
||||
{
|
||||
if (Universe is not IUniverse universe)
|
||||
return;
|
||||
@@ -57,8 +59,13 @@ public class PhysicsCoroutineManager : UniverseObject
|
||||
physicsEngine = universe.GetUniverseObject<IPhysicsEngine2D>();
|
||||
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
||||
{
|
||||
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
||||
universe.OnUpdate -= OnUpdate;
|
||||
foundPhysicsEngine.OnPhysicsStep.AddListener(OnPhysicsStep);
|
||||
universe.OnUpdate.RemoveListener(OnUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
public PhysicsCoroutineManager()
|
||||
{
|
||||
delegateOnUpdate = OnUpdate;
|
||||
}
|
||||
}
|
||||
|
@@ -4,8 +4,10 @@ namespace Syntriax.Engine.Physics2D;
|
||||
|
||||
public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
|
||||
{
|
||||
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
||||
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
||||
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; } = new();
|
||||
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; } = new();
|
||||
|
||||
private readonly Event<IUniverse, IUniverse.UpdateArguments>.EventHandler delegateOnPreUpdate = null!;
|
||||
|
||||
private float physicsTicker = 0f;
|
||||
private int _iterationPerStep = 1;
|
||||
@@ -178,7 +180,7 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
|
||||
colliderCollector.Assign(universe);
|
||||
rigidBodyCollector.Assign(universe);
|
||||
|
||||
universe.OnPreUpdate += OnEnginePreUpdate;
|
||||
universe.OnPreUpdate.AddListener(OnEnginePreUpdate);
|
||||
}
|
||||
|
||||
protected override void OnExitingUniverse(IUniverse universe)
|
||||
@@ -189,12 +191,12 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
|
||||
colliderCollector.Unassign();
|
||||
rigidBodyCollector.Unassign();
|
||||
|
||||
universe.OnPreUpdate -= OnEnginePreUpdate;
|
||||
universe.OnPreUpdate.RemoveListener(OnEnginePreUpdate);
|
||||
}
|
||||
|
||||
private void OnEnginePreUpdate(IUniverse sender, UniverseTime engineTime)
|
||||
private void OnEnginePreUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
||||
{
|
||||
physicsTicker += engineTime.DeltaTime;
|
||||
physicsTicker += args.EngineTime.DeltaTime;
|
||||
|
||||
while (physicsTicker >= IterationPeriod)
|
||||
{
|
||||
@@ -207,11 +209,15 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
|
||||
{
|
||||
collisionDetector = new CollisionDetector2D();
|
||||
collisionResolver = new CollisionResolver2D();
|
||||
|
||||
delegateOnPreUpdate = OnEnginePreUpdate;
|
||||
}
|
||||
|
||||
public PhysicsEngine2D(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
|
||||
{
|
||||
this.collisionDetector = collisionDetector;
|
||||
this.collisionResolver = collisionResolver;
|
||||
|
||||
delegateOnPreUpdate = OnEnginePreUpdate;
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,11 @@ namespace Syntriax.Engine.Physics2D;
|
||||
|
||||
public class PhysicsEngine2DStandalone : IPhysicsEngine2D
|
||||
{
|
||||
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
||||
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
||||
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; } = new();
|
||||
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; } = new();
|
||||
|
||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||
|
||||
private readonly List<IRigidBody2D> rigidBodies = new(32);
|
||||
private readonly List<ICollider2D> colliders = new(64);
|
||||
@@ -29,13 +32,16 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
|
||||
foreach (ICollider2D collider2D in rigidBody.BehaviourController.GetBehaviours<ICollider2D>())
|
||||
colliders.Add(collider2D);
|
||||
|
||||
rigidBody.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
||||
rigidBody.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
||||
rigidBody.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
||||
rigidBody.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
||||
}
|
||||
|
||||
public void RemoveRigidBody(IRigidBody2D rigidBody)
|
||||
{
|
||||
rigidBodies.Remove(rigidBody);
|
||||
|
||||
rigidBody.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
||||
rigidBody.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
||||
}
|
||||
|
||||
public void Step(float deltaTime)
|
||||
@@ -172,17 +178,17 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
|
||||
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
|
||||
}
|
||||
|
||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour)
|
||||
private void OnBehaviourAdded(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments args)
|
||||
{
|
||||
if (behaviour is not ICollider2D collider2D)
|
||||
if (args.BehaviourAdded is not ICollider2D collider2D)
|
||||
return;
|
||||
|
||||
colliders.Add(collider2D);
|
||||
}
|
||||
|
||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
|
||||
private void OnBehaviourRemoved(IBehaviourController sender, IBehaviourController.BehaviourRemovedArguments args)
|
||||
{
|
||||
if (behaviour is not ICollider2D collider2D)
|
||||
if (args.BehaviourRemoved is not ICollider2D collider2D)
|
||||
return;
|
||||
|
||||
colliders.Remove(collider2D);
|
||||
@@ -192,11 +198,17 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
|
||||
{
|
||||
collisionDetector = new CollisionDetector2D();
|
||||
collisionResolver = new CollisionResolver2D();
|
||||
|
||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||
}
|
||||
|
||||
public PhysicsEngine2DStandalone(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
|
||||
{
|
||||
this.collisionDetector = collisionDetector;
|
||||
this.collisionResolver = collisionResolver;
|
||||
|
||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user