Demo: N-Body Problem
This demo demonstrates N:N relationships in an ECS, and how to set up and simulate an arbitrary number of bodies in a generic way.
Source Code
This demo is available for the following:
MonoGame | Godot | Flax | Unigine | Stride | Raylib | NeoAxis |
---|---|---|---|---|---|---|
Video (Godot Version)
Remarks
Case in point here is not raw performance (although the basic GDscript-driven line trail rendering easily eats 90% of the Godot rendering time). Instead, note how short and concise the simulation loop stays - without as much as a single reverse lookup.
cs
// Clear all forces
_accumulator.Blit(new Acceleration());
// Accumulate all forces (we have only 1 attractor stream, this will enumerate each sun 3 times)
_accumulator.For((ref Acceleration acc, ref Body self, ref Body attractor) =>
{
if (self == attractor) return; // (we are not attracted to ourselves)
var distanceSquared = Mathf.Max(0.001f, MathF.Pow(Vector2.DistanceSquared(attractor.position, self.position), 0.75f) / 100000f);
var direction = Vector2.Normalize(attractor.position - self.position);
acc.Value += direction * attractor.mass / distanceSquared / self.mass;
// Just a pinch of dark matter to keep things together a bit more
acc.Value -= self.position * 0.005f / self.mass;
});
// Integrate accelerations, velocities, and positions
_integrator.For(
uniform: (float)delta,
action: static (float dt, ref Acceleration accel, ref Velocity velocity, ref Position position) =>
{
velocity.Value += dt * accel.Value;
position.Value += dt * velocity.Value;
});
State and Structure are stored in the Components on the Entities:
- 1x
Body
as Plain Component (contains mass and last position) - Nx
Body
as Entity-Entity Relation (once for each other body) - 1x
Position, Velocity, Acceleration
(for physics sim)
The state is transferred into the Game Engine directly talking to the Nodes.