An ergonomic physics API for 2d and 3d bevy games

An ergonomic physics API for 2d and 3d rapier)


An ergonomic physics API for 2d and 3d bevy games. (powered by rapier)

What it looks like


For a 2d game:

For a 3d game:

Supported Bevy Versions

bevy heron
0.6 1
0.5 0.4 - 0.13
0.4 0.1 - 0.3

Design principles

  • Use bevy types, resources and components when possible (Vec3, Quat, Transform, Events, etc.)
  • Provide a single API that works for both 2d and 3d. (Like bevy does)
  • Data oriented. Using this library should feel like its a part of bevy.
  • Avoid asking the user to lookup in resources via handles. Data should be accessible and modifiable directly in components.
  • Hide the actual physics engine. This is an implementation detail the user shouldn't have to worry about.
    • But, allow advanced users to access the underlying rapier resources, so the user is never blocked by a missing element in the API of heron.

Feature flags

One must choose to use either 2d or 3d. If neither of the two features is enabled, the PhysicsPlugin won't be available.

  • collision-from-mesh Add a component to generate convex hull collision for a mesh.
  • 3d Enable simulation on the 3 axes x, y, and z.
  • 2d Enable simulation only on the first 2 axes x and y.
  • debug-2d Render 2d collision shapes.
  • enhanced-determinism Enable rapier's enhanced-determinism

How does this project compare to bevy_rapier?

bevy_rapier plugin is an excellent option and should definitely be considered.

Here are some key differences between the two projects:

  • heron tries to provide a smaller, simpler API that is easier to use. bevy_rapier is more complete and powerful, but a bit more complex.
  • heron mostly hides the underlying physics engine, so you don't have to use rapier directly nor nalgebra. bevy_rapier asks the user to deal directly with rapier and nalgebra.
  • heron is focused on games only. bevy_rapier targets all kind of physics simulation applications (incl. games).
  • bevy_rapier is actively maintained by dimforge, the developer of rapier. heron is also active, but cannot evolve as fast as bevy_rapier can.

heron is probably more suited for simple games and game-jams, where the ease of learn/use is especially valuable and where the lack of advanced feature isn't problematic.

bevy_rapier is probably more suited for bigger/complex games and other types of physics simulations, where it may be better to learn/use a more exhaustive/complex API.

Contribute / Contact

You can open issues/discussions here or you can discuss with me (Jomag#2675) in the bevy discord

See how to contribute


Collection of the latest Issues



Comment Icon1

Well, the title explains it: it would be nice to support joints and motors.

bevy_rapier implements these as separate entities. For example, one does:

This seems like the most reasonable way of doing things. It is

My suggestion would be to have something like a "Joint" struct, containing the data necessary to construct a joint, including two entities. Then the "Joint system" could go over all the changed joint components each step, creating/modifying/deleting joints from the JointSet as needed. The motor configuration could either be a separate component or an optional part of the joint component (the advantage of doing it the second way is that the type of a motor configuration depends on the joint type - so this allows us to prevent people from adding incompatible motor and joints to the same entity).

I'm imagining using this something like

I'm happy to take a crack at implementing this myself if this sounds like a reasonable solution.



Comment Icon1

If I understand correctly from what I've seen in bevy_rapier2d, it looks like it actually stores all of the simulation data such as rigid body positions, etc. in the bevy ECS, by implementing the ComponentSet trait. With the way we have heron right now we are storing the physics world data in Bevy resources that use arena based storage.

I'm curious if that has any advantages performance or otherwise and if that would be a useful strategy in heron or not. I'm mostly just musing over the possibility, but do you have any ideas why we would want to or not want to do that?



Comment Icon0

Even if it is too small and far from complete, "some" documentation is better than "none".

Let's publish the guide.



Comment Icon6

Right now, the only way to control kinematic bodies is by manually changing their transform. However, collisions are not taken into account by default, delegating that logic to the final user. This would be really useful to have even in basic games, such as platformers, where the player needs to collide with the floor.

For instance, Godot includes some high-level functions to handle this behavior, as explained in its documentation: Movement and collision and Detecting collisions.

This was discussed a while ago in the Bevy's discord physics channel, where Rapier's developer said:

Almost no physics engines compute contacts between two non-dynamic bodies (however kinematic bodies do affect dynamic bodies). So you are supposed to use shape-casting to detect collision with the static environment. The godot "move_and_collide" and "move_and_slide" are just higher-level operations which are based on shape-casting.



Comment Icon7

Here are some proposed convenience shapes for 2d that mostly don't exist directly in Rapier but are easy to implement. The argument to have them is because when dealing with 2d, people think in 2d terms. It's weird to refer to a circle as a "sphere", for instance. We can also use Vec2 instead of Vec3 to define them where vecs are involved.

I think we can make them in a special Body2 enum that gets translated into Body underneath.



Comment Icon1

I create this issue issue to track the biggest missing pieces of documentation that are required to publish an "initial version" of the guide.

(Thanks @faassen for the list)

  • How to define a body type (Static, Kinematic, Dynamic and Sensor)
  • PhysicMaterial
  • Collision detection
  • 2d gotchaes (incl. rotation in 2d is around the z axis.)
  • Change/Define velocity, acceleration, force and impulse
  • How to acces Rapier directly (#43)


Comment Icon7

We have a use case where we want to access shape data in the renderer code. For instance, ConvexHull creates a set of points that defines the convex hull depending on the points you give it. It should be possible to access this data through a Heron API. This issue is to remind us to think about this.

In Rapier, once you have the shape, you can call this:

Where as_convex_polygon is a typecast and then points is the method that returns the points to draw.

Do we want to expose some kind of typecast API that can fail like this or is there another pattern that would work better? I know absolutely nothing about the reflection system of Bevy, is that relevant?

We need a Heron version of a convex polygon, that exposes Bevy vectors instead of Rapier points.

See also #43 as a fallback on how to get to the Rapier world. This could be a quick way to implement it without any new Heron APIs for the debug renderer, but in the longer term it would be better to expose this information in some nice Heron API.



Comment Icon0

Add an Body::TriMesh enum variant that will allow creation of collider meshes based on bevy verteex position and indices data.

Also consider providing an easy interface of constructing those collider meshes from bevy's mesh handles



Comment Icon0

A sensor is NOT an actual physics body. But that doesn't mean we don't want to move or rotate it. There are plenty of use-case where we may want to move some sensor without having to make it a "dynamic" body. It would be much easier if I could simply use the velocity component for them.

Thinking about it, the Velocity could work for any entity. And the behavior would be:

  • For dynamic bodies: Apply the velocity, and let rapier continue the simulation (incl. mutating the velocity)
  • For kinematic bodies: Update the next_position at each steap and let rapier continue the simulation (not mutating the velocity)
  • For static bodies and sensors: Teleport the body each frame at the desired velocity ignoring physics rules.
  • For an entity without the Body component: Update the Transform each frame at the desired velocity.


Comment Icon0

As a User, I want an easy way to query for components of the entities involved in a collision, so that it is easier to read/update components as part of the reaction to the event.

Here is how usage could look like:



Comment Icon0

As a User, I wan't to get clear and quick feedback when I make a mistake, so that I avoid spending time guessing/debuging in order to make my game work.

For example the Body component needs the entity to also have a GlobalTransoform. And a Velocity works only on dynamic bodies.

When a required components is missing it can be considered a programming mistake of the user of this library, and Heron should at least report the situation, so the user is aware of it.


Find the latest versions by id

v2.0.1 - Feb 20, 2022

2.0.1 (2022-02-20)

Bug Fixes

  • collision-from-mesh: don't fail if there is no render plugin registered (#196) (155c34c)

v2.0.0 - Feb 20, 2022

2.0.0 (2022-02-20)


  • CollisionEvent and CollisionData no longer implement Copy, Eq, and PartialEq


  • add normals to CollisionData in events (#189) (b89446c)


  • readme: update example to bevy 0.6 syntax (#191) (507f4f4)

v1.2.0 - Feb 19, 2022

1.2.0 (2022-02-19)


  • generate collision shapes from mesh via the PendingConvexCollision component (behind the collision-from-mesh feature flag) (#190) (086a6a6)

v1.1.0 - Jan 25, 2022

1.1.0 (2022-01-25)


v1.0.1 - Jan 23, 2022

Since 1.0.1-rc.1

Bug fixes

  • debug-2d: crash when despawning recursivly an entity (#178)

Since 0.13.0

Breaking changes

  • Require bevy version 0.6
  • Require rust 1.57
  • Remove debug-3d feature (This will hopefully be reintroduced when upstream dependencies will be compatible with bevy 0.6)

v1.0.1-rc.1 - Jan 09, 2022

Breaking changes

  • Require bevy version 0.6
  • Require rust 1.57
  • Remove debug-3d feature (This will hopefully be reintroduced when upstream dependencies will be compatible with bevy 0.6)

v0.13.0 - Jan 01, 2022

Breaking changes

  • The CollisionShape is now marked #[non_exhaustive]
  • The AppBuilderExt trait and the add_physics_system is removed
    • This was no longer necessary since #109


  • Cone collision shape (#158)
  • Cylinder collision shape (#159)
  • Custom collision shape (#160)
  • Damping component (#164)


  • Despawn not working if simulation is paused

v0.12.1 - Oct 24, 2021


  • KinematicVelocityBased bodies not being moved by velocity (#148).
  • Collision events not being fired for kinematic bodies (#142).

v0.12.0 - Oct 24, 2021

Breaking changes

  • The DebugColor resource no longer implement From<Color>. That's because it now defines multiples colors, not one.
  • The required version of rapier is now ^0.11.1
  • The minimum supported version of rust is now 1.56.0


  • Debug renderer for 3d, behind the debug-3d feature flag (#151).


  • The collision shapes now have different colors based on the type of body (static, dynamic, kinematic, sensor).

v0.11.1 - Aug 23, 2021

Bug fixes

  • Too broad scaling of all shapes with debug mode (#138)

v0.11.0 - Jul 19, 2021

Breaking changes

  • CollisionShape::Cuboid and CollisionShape::ConvexHull now have rounded member (that can be None)


  • PhysicsWorld system parameter that can be used for ray and shape casting (#129)

v0.10.1 - Jul 19, 2021


This release is yanked because breaking changes have accidentally landed in this minor semver bump.

It has been re-released under the version number 0.11.0 to reflect the presence of breaking changes.

Breaking changes

  • CollisionShape::Cuboid and CollisionShape::ConvexHull now have rounded member (that can be None)


  • PhysicsWorld system parameter that can be used for ray and shape casting (#129)

v0.10.0 - Jul 12, 2021

Breaking changes

  • PhysicsSteps::duration now returns a PhysicsDuration instead of Duration


  • Variable timestep mode for PhysicsSteps (#123)

v0.9.1 - Jun 30, 2021

Bug fixes

  • Empty documentation on docs.rs

v0.9.0 - Jun 29, 2021

Breaking changes

  • The cargo feature debug has been replaced by debug-2d. (thanks @zicklag)
  • No cargo feature is enabled by default. One must explictly choose between 2d or 3d. (Thanks @zicklag)
  • The heron_rapier::rapier module has been replaced by heron_rapier::rapier2 in 2d and heron_rapier::rapier3d in 3d.
  • Required version of rapier is now ^0.9.2. (Thanks @zicklag)
  • RigidBody::Static is replaced by RigidBody::KinematicPositionBased and RigidBody::KinematicVelocityBased. (Thanks @zicklag)
  • The Layer trait now works with u32 instead of u16, increasing the maximum number of layers up to 32. (Thanks @zicklag)


  • Preserve Z translation in 2d. (#120, thanks @zicklag)

Bug fixes

  • Impossiblity to disable render feature in 2d (#118, thanks @zicklag)
  • Compilation errors for 3d users (#125)

v0.8.0 - Jun 07, 2021

Breaking changes

  • There is a new variant HeightField to the CollisionShape enum


  • HeightField collision shape (#102, thanks @elegaanz)

v0.7.0 - May 31, 2021

Breaking changes

  • The CollisionEvent now contains a pair of CollisionData instead of a pair of Entity
  • The physics step rate is not defined on the plugin type anymore. It is replaced by a PhysicsSteps resource.
  • The IntegrationParameters can no longer be defined when installing the plugin. The IntegrationParameters resource should should be inserted/mutated instead.
  • The Velocity and Transform are now updated during the CoreStage::PostUpdate. If a user-system needs to run after the physics update, it should explicitly declares that dependency using the PhysicsSystem labels.


  • More data in collision events (#103)
  • SensorShape component to mark individual collision shape as sensor (#104)
  • Runs physics step at most once per frame (#109)

v0.6.0 - May 24, 2021

Breaking changes

  • The Body component is renamed to CollisionShape
  • The BodyType component is renamed to RigidBody and is now mandatory. (The rigid bodies are no longer automatically "dynamic" when the component is not found)
  • The BodyHandle component is removed. The rapier's RigidBodyHandle and ColliderHandle are now used instead.


  • Allow to define (multiple) collision shapes in the child entity of a rigid body (#97)
  • Collision layers (#101)

Bug fixes

  • Frame delay after a spawn/update of the entity transform (#92)
  • The acceleration component is now registered for bevy reflection

v0.5.1 - May 01, 2021

PhysicsTime resource

The PhysicsTime resource can be used to change the time-scale of the physics engine.

Thanks @yaymalaga

v0.5.0 - Apr 18, 2021

⚠ Dependency requirements updated (breaking)

The required version of rapier2d is bumped to ^0.8.0

⚠ Support defining friction

A new public field friction has been added in PhysicMaterial. As the name suggest, it allows to define the friction that should be applied when two rigid bodies are in contact.

Thanks @yaymalaga

v0.4.0 - Apr 17, 2021

⚠ Dependency requirements updated (breaking)

The required version of bevy is bumped to ^0.5.0 The required version of rapier2d is bumped to ^0.7.2 The required version of rapier3d is bumped to ^0.8.0

Feature flags of public dependencies

Heron no longer enables any feature flag for rapier. That way the end-user can freely choose the rapier feature flags.

v0.3.0 - Mar 21, 2021

⚠ ConvexHull collision shape

There is a new variant in the Body enum: ConvexHull. It takes a list of points, and the body shape will be the smallest possible convex shape that includes all the given points.

Thanks @faassen

Acceleration component

A new Acceleration component make possible to apply and linear and angular accelerations. It is by extension also possible to apply a force if you know the mass: acceleration.linear = force / mass.

Thanks @ryo33

RotationConstraints component

A new RotationConstraints component make possible to prevent rotation around the given axes.


  • The opacity has been increased for the default color of debug shapes.

v0.2.0 - Mar 07, 2021

⚠ Physics update systems (breaking)

The physics step run at a fixed rate (60 updates per second by default). Therefore, it is not in sync with the frame update (that runs as many times per second as possible).

But a user may want to (and sometime have to) run some systems synchronously with the physics step.

This is why two stages are now public:

  • stage::ROOT: the root schedule stage that contains the physics step and run at a fixed rate (60 updates per second by default)
  • stage::UPDATE: a child (parallel) system stage that runs before each physics step

But most of the time, users shouldn't have to use the stage directly, because an add_physics_system extension function is provided on AppBuilder and can be used like add_system, except systems added with add_physics_system will run during the physics update.

This is a breaking change: Updating the transforms/velocities or any other physics component of rigid bodies must be done in the physics update stage. Make sure to add theses systems using the new add_physics_system extension function on AppBuilder.

⚠ New PhysicMaterial component that replaces Restitution (breaking)

There is now a PhysicMaterial component which can be used to define both the restitution (how bouncy) and density (how heavy) the material is.

In the future it will be extended to define more physics properties, like the friction.

Since the restitution is now defined in PhysicMaterial, the Restitution component has been removed.

⚠ Kinematic bodies (breaking)

There is a new variant to BodyType: Kinematic. That makes possible to create "kinematic" bodies. A kinematic body is controlled programmatically (usually by updating the transform) and affect the other bodies normally, but is not affected by them.

⚠ Dependency requirements updated (breaking)

The required version of rapier is bumped to ^0.6.1

All components are registered for reflection

All components now implement Default and Reflect and are registered to bevy reflect system. That should make be possible to use heron components in serialized scene for hot-reloading.

Public constructor to BodyHandle

BodyHandle now has a public constructor. Advanced users may create rigid bodies and colliders using directly the rapier API (adding them to the RigidBodySet and ColliderSet resources), and then add a BodyHandle component to the entity so that heron's will handle velocity and update the bevy transforms.

Tanks @MGlolenstine

v0.1.1 - Feb 16, 2021

Fix incorrect internal version requirements

A problem happened during the release of 0.1.0, and some crates (incl. the root crate heron) where requiring invalid version of the other heron crates.

v0.1.0 - Feb 15, 2021

⚠ Dependency requirement updated (breaking)

The required rapier version is now ^0.5.0.

⚠ New collision shapes (breaking)

The variants Body::Capsule and Body::Cuboid have been added, allowing to create respectively capsule and cuboid collision shapes

New BodyType component

By default, the rigid-bodies are dynamic. A BodyType can be attached to make it:

  • Static (with BodyType::Static) so that it doesn't move.
  • Sensor (with BodyType::Sensor) so it doesn't move and doesn't affect other bodies. (Only useful for listening to collision events)


  • Misplaced debug render at startup
  • Incorrect angular velocity in 2d

v0.1.0-alpha.1 - Jan 30, 2021

Features flags

  • 3d (enabled by default) Enable simulation on the 3 axes x, y, and z. Incompatible with the feature 2d.
  • 2d Enable simulation only on the first 2 axes x and y. Incompatible with the feature 3d, therefore require to disable the default features.
  • debug Render collision shapes. Works only in 2d for now, support for 3d will be added later.

Importatn: Either 2d or 3d (but not both) must be enabled. If none or both of theses two features are enabled, the PhysicsPlugin won't be available.

PhysicsPlugin plugin

Add the PhysicsPlugin to setup collision detection and physics simulation. It also registers rapier's RigidBodySet , ColliderSet, JointSet, IntegrationParameters, BroadPhase and NarrowPhase in the resources.

Gravity resource

The resource Gravity defines the world's gravity. Gravity is disabled by default. You may override or mutate the Gravity resource to change the world's gravity.

Body component

A Body component can be added to make the entity a dynamic rigid body with the given shape.

The position of the body is defined by the bevy GlobalTransform component. Updating the GlobalTransform, will teleport the body ignoring physics rules.

Every frame the Transform will be updated to reflect the body position in the world.

Heron will automatically handle replacement and removal of the body (when the component mutated/removed or when the entity is despawned)

At the moment, only spheres are supported. More shape will be added in the future. Support for static and kinematic bodies will be added later too.

Velocity component

Add the Velocity component to an entity to define/update or read the velocity of a dynamic body.

The entity, must also have a Body component and a GlobalTransform.

Restitution component

The Restitution component can be added to define the restitution coefficient of a body.

CollisionEvent event

One can read from Events<CollisionEvent> to be notified when collisions start and stop.

Information - Updated Feb 27, 2022

Stars: 194
Forks: 39
Issues: 18

Repositories & Extras

Arsenal 2D retro Rust Game engine

Katharos Technology is focused on producing our first game prototype, bevy game engine and our own Katharos...

Arsenal 2D retro Rust Game engine

Grumpy Visitors 2D Rust game for code reference and learning

Grumpy Visitors is a top-down 2D action arcade game

Grumpy Visitors 2D Rust game for code reference and learning

Rust Game Remake

Remake in rust of a game I made during the here

Rust Game Remake

A 3d rust game using OpenGl and Emscripten to build for the wasm32-unknown-emscripten

It can also run standalone, developed and tested on Linux but will

A 3d rust game using OpenGl and Emscripten to build for the wasm32-unknown-emscripten

Rust Game of Life

This is a simulator of Conway's Game of Life in Rust, using SDL2 to render the game graphically

Rust Game of Life

INOX - Rust Game engine integrated in Blender

It's a Game Engine written in Rust with some bindings for external libs and with Blender as editor

INOX - Rust Game engine integrated in Blender

Rust GameBoy Advanced Emulator

Building this project on linux requires cmake and gtk3

Rust GameBoy Advanced Emulator

A Rust Game Engine

In an effort to learn the Rust language (because I am a nut), I am building a game engine

A Rust Game Engine

A Rust GameBoy emulator!

TetrisZelda: Link's Awakening

A Rust GameBoy emulator!

Another Rust game engine

It's started as a rust version of the tutorial from

Another Rust game engine
Facebook Instagram Twitter GitHub Dribbble