An ergonomic physics API for bevy games.

Overview

Heron

License Crates.io Docs Build Zenhub

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

How it looks like

fn main() {
  App::build()
    .add_plugins(DefaultPlugins)
    .add_plugin(PhysicsPlugin::default()) // Add the plugin
    .add_resource(Gravity::from(Vec3::new(0.0, -9.81, 0.0))) // Optionally define gravity
    .add_startup_system(spawn.system())
    .run();
}

fn spawn(commands: &mut Commands) {
    commands

        // Spawn any bundle of your choice. Only make sure there is a `GlobalTransform`
        .spawn(SpriteBundle::default())

        // Make it a physics body, by attaching a collision shape
        .with(Body::Sphere { radius: 10.0 })

        // Optionally define a type (if absent, the body will be *dynamic*)
        .with(BodyType::Static)
        
        // Optionally define the velocity (works only with dynamic and kinematic bodies)
        .with(Velocity::from(Vec2::unit_x() * 2.0));
}

Installation

For a 3d game:

bevy = "^0.4.0"
heron = "0.1.1"

For a 2d game:

bevy = "^0.4.0"
heron = { version = "0.1.1", default-features = false, features = ["2d"] }

With the git version of bevy:

bevy = { git = "https://github.com/bevyengine/bevy.git", branch = "main" }

# ATTENTION: The code may not compile. And if it does compile, it may not work properly!
# Be aware, that it might contains unreleased features and breaking changes too.
# Checkout the changelog: https://github.com/jcornaz/heron/blob/next-bevy/CHANGELOG.md#unreleased
heron = { git = "https://github.com/jcornaz/heron.git", branch = "next-bevy" }

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 look like it is 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 care about.
    • But, allow advanced users to access the underlying rapier resources, so a user is never blocked by a missing element in the API of heron.

Feature flags

One must choose to use either 2d or 3d (but not both). If none of theses two features is enabled, the PhysicsPlugin won't be available.

Enabled by Default

  • 3d Enable simulation on the 3 axes x, y, and z. Incompatible with the feature 2d.

Optional

  • 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, support for 3d will be added later.

Motivation

I think rapier is very powerful as a physics engine. But using it directly or via bevy_rapier in a bevy game is not ergonomic enough for my taste.

Ideally I would like to have the power of rapier accessible behind an API focused on bevy games.

Contribute / Contact

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

See how to contribute

Comments
  • feat: add configurable StagedPhysicsPlugin

    feat: add configurable StagedPhysicsPlugin

    Closes: #170

    Added the StagedPhysicsPlugin which allows you to pass in stage labels for the main physics schedule, the post physics stage, and tick stage.

    The main physics needs to be a schedule and not just a stage since it uses sub stages. The other two are fine as just stages.

    Creating as a draft since I'm not sure the best way to add tests for this. I made an example custom_schedule.rs which is basically just the demo example using the new plugin.

    I'm still somewhat new to bevy/heron so let me know if the comments I added don't make sense

    enhancement 
    opened by JRMurr 23
  • feat: allow to define layers for collision shapes generated by `PendingConvexCollision`

    feat: allow to define layers for collision shapes generated by `PendingConvexCollision`

    This PR adds an additional field to the PendingConvexCollision to set collision layers. I realized that setting default collision is needed only for the generated collision. In all other cases user can define needed collision layer explicitly. Closes #217.

    opened by Shatur 18
  • feat: colliding entities component

    feat: colliding entities component

    Closes #207.

    I added a component that automatically filled with colliding object entities.

    Things to discuss:

    • I used CollidingEntities because the suggested Collision could be confusing (and already used in Bevy, but not in prelude). Is this okay name?
    • Should we provide Deref for CollidingEntities?
    enhancement 
    opened by Shatur 14
  • KinematicVelocityBased bodies are updated by Velocity.

    KinematicVelocityBased bodies are updated by Velocity.

    Should fix #145 also help with #142 test not passing and replace #146.

    Fixed the problem by reusing update_rapier_velocity for dynamic and made for all bodies that can_have_velocity. So removed redundant apply_velocity_to_kinematic_bodies in favor of update_rapier_position.

    I think this should be a bit urgent since it's a somewhat 'core' functionality and a few people have asked help on why it wasn't working in the bevy discord.

    opened by edgarssilva 14
  • feat!: add normals to `CollisionData` in events

    feat!: add normals to `CollisionData` in events

    Adds normal data from ContactManifoldData::normal to the CollisionData struct.

    Benefits

    • Normal vector added to collision data

    Downsides

    • I had to remove Copy from CollisionData due to the normals being in a Vec<Vec2>. We could just provide the first normal Vec2 as an Option<Vec2>, but I'm not sure whats the best option for this.

    Fixes https://github.com/jcornaz/heron/issues/188

    enhancement breaking 
    opened by tqwewe 12
  • Add a `PhysicsWorld` Parameter ( Ray Casting )

    Add a `PhysicsWorld` Parameter ( Ray Casting )

    Resolves #35 .

    Untested, but it should provide a very convenient and easy-to-use API for ray and shape casting. Extra queries such as intersection queries can be added easily later, too.

    I'll add a example to test that it's working before marking it ready to merge.

    opened by zicklag 11
  • Use Separate Cargo Features for Debug 2D and 3D

    Use Separate Cargo Features for Debug 2D and 3D

    Currently, the heron crate doesn't expose anything unless either the 2D or 3D features are enabled, but enabling either of those features also enables the debug renderer. This makes it impossible to use heron without enabling the debug rendering crates.

    My projects use Bevy Retrograde, which uses a custom renderer on top of Bevy that won't compile when bevy's rendering features are enabled. Because the debug crates require Bevy's rendering features, there's no combination of features under which I can compile heron for use in Bevy Retrograde.

    This change makes it required to pass in the debug-2d or debug-3d features in order to actually include the heron_debug. This allows me to run my project without including bevy's rendering features.

    I'm not sure this is the best way to do it and I'm totally open to any other options, as long as there is some way to compile without needing heron_debug.

    opened by zicklag 11
  • Debug-2d feature makes scales not work

    Debug-2d feature makes scales not work

    When I enable the debug-2d feature transform scales seem to stop working, also I have a little system to zoom in and out the camera that also stops working. With this it becomes a bit hard to debug because the size of the debugs don't match the sprite.

    opened by edgarssilva 10
  • feat!: Body::TriMesh implementation

    feat!: Body::TriMesh implementation

    Opening this as a draft for https://github.com/jcornaz/heron/issues/41 and as a place to ask for help with potential issues regarding it.

    In it's current state i'm faced with the following errors.

    thread '<unnamed>' panicked at 'index out of bounds: the len is 128 but the index is 128', C:\Users\domen\.cargo\registry\src\github.com-1ecc6299db9ec823\rapier3d-0.5.0\src\dynamics\solver\interaction_groups.rs:89:21

    I noticed that this feature is under the 'parallel' feature and tried to disable it. Once I did that I got the following error.

    thread 'main' panicked at 'assertion failed: proxy.aabb.mins[dim] <= self.max_bound', C:\Users\domen\.cargo\registry\src\github.com-1ecc6299db9ec823\rapier3d-0.5.0\src\geometry\broad_phase_multi_sap.rs:171:13

    As of now all the code required to produce the Vec and Vec<[u32; 3]> pair from Asset lives in my project https://github.com/Dmajster/radwars. So if you wish to reproduce this errors or help out I think this would be the fastest path.

    I also think this would be a great feature to move this into Heron down the road.

    opened by Dmajster 10
  • Activated all collision types

    Activated all collision types

    Just a simple method call also events were already activated so the collision types was basically the same. Had to do it in 3 commits because I'm not getting any intellisense and no compile errors so I wen't for trial and error. Should be able to fix #140.

    opened by edgarssilva 9
  • Implement a HeightField collision shape

    Implement a HeightField collision shape

    Resolves #62

    Some notes:

    • I went with a Vec<Vec<f32>> to define the heights, both in 2D and 3D (and only take the first sub-vec in account in 2D). I couldn't get #[cfg(features)] to work as I wanted
    • I'm not sure about the debug implementation, because I don't know much about lyon. I'll probably add a heightfield to the debug example to see if it does what I expect.
    • The scale that rapier expects is actually more the dimensions of the field, so I had to do a little conversion.
    • Also, it looks like rapier/parry always centers the heightfield. Is there anything I need to do to update the transform of a collision shape in rapier when it is updated in bevy?
    opened by elegaanz 9
  • Collision events for sensor always firing, PhysicsLayer issue or incorrect setup??

    Collision events for sensor always firing, PhysicsLayer issue or incorrect setup??

    i have 4 physics layers in my app, the entitys that can collide have collision layers like below, the player, and the enemys have collision shapes on child entitys, im not sure if its because i have the physics layers organized wrong or if i have some other thing shooting me in the foot, but ive tried quite a few different combos of groups/masks/layers to no real effect. i also noticed that no matter what i do my players/enemys always collide, even when both have CollisionLayers::none() or i mask them out

    i took the collision detection event system from the examples to test the sensor and i noticed that my player and skeleton entitys have an obscenely large amount of groups/masks

    heres the output from an event reader for collisionevent

    Collision started between CollisionData { rigid_body_entity: 2729v0, collision_shape_entity: 2729v0, collision_layers: CollisionLayers { groups: 8, masks: 2 }, normals: [] } and CollisionData { rigid_body_entity: 2812v0, collision_shape_entity: 2813v0, collision_layers: CollisionLayers { groups: 4294967295, masks: 4294967295 }, normals: [] }
    Collision stopped between CollisionData { rigid_body_entity: 2729v0, collision_shape_entity: 2729v0, collision_layers: CollisionLayers { groups: 8, masks: 2 }, normals: [] } and CollisionData { rigid_body_entity: 2812v0, collision_shape_entity: 2813v0, collision_layers: CollisionLayers { groups: 4294967295, masks: 4294967295 }, normals: [] }
    

    im marking my Sensor entity with :

    collision_layers: CollisionLayers::none()
    					.with_group(PhysicsLayers::Sensor)
    					.with_mask(PhysicsLayers::Player)
    

    im marking my walls with:

    collision_layers: CollisionLayers::none()
                        .with_group(PhysicsLayers::World)
                        .with_masks(&[PhysicsLayers::Player, PhysicsLayers::Enemies])
    

    im spawning my player with:

    collisionlayers: CollisionLayers::none()
                        .with_group(PhysicsLayers::Player)
    

    and im marking my enemies with

    collisionlayers: CollisionLayers::none()
                                    .with_group(PhysicsLayers::Enemies)
    

    physicslayers is my enum for things that can collide

    #[derive(PhysicsLayer)]
    pub enum PhysicsLayers {
    	Sensor,
        World,
        Player,
        Enemies,
    }
    
    bug 
    opened by Hellzbellz123 2
  • Collision events not firing

    Collision events not firing

    I've made an example project where a collision event should fire. It does not fire in 9/10 case though

    https://github.com/stillonearth/bevy_dice/tree/c18abc62eb490aa0418d824bd23c2662eea7f48d

    I've collider issues when colliding objects on high velocities, but it seems somehow related here. Collision itself happens, though no events.

    to-investigate 
    opened by stillonearth 1
  • Possible Issue with Raycasting

    Possible Issue with Raycasting

    Desktop Screenshot 2022 07 20 - 12 34 51 83

    ~~The screenshot above was taken by using CodeLLDB and stepping through the execution of Rust code.~~

    ~~As you can see, pre-normalization the ray vector is about (12, 15, -98) which is actually a unit vector with its magnitude x100.~~ ~~That means we'd expect the normalized vector to be around (0.12, 0.15, -0.98)~~

    ~~After normalization (assigned to direction) the vector is (-0.98, 0, 0).~~

    ~~The -0.98 value placed in the x scalar slot should be placed in the z scalar slot, and the x and y scalars are not present at all.~~

    ~~Now, CodeLLDB isn't perfect, it may not be mapping the memory values correctly, so this may essentially be a visual bug with the debugger.~~

    ~~However, I am experiencing a bug where I'm casting a ray through some collider shapes, and the ray cast always returns None, even when I confirm the start and ray vectors would correctly cause the ray to pass through the location of the collider shapes.~~

    ~~The vector normalization misalignment is the best lead I have so far.~~

    For the sake of completeness,, I've attached below a copy a post I made asking for help in the Bevy Discord server. If there's an obvious bug there that would cause the raycast to not detect the collision shapes, then I think it's reasonable to chalk up the erroneous vector normalization to a debugger memory layout bug.

    However, if the attached code looks correct, then as above, this vector normalization bug is the best lead I have for a root cause.

    help.md

    to-investigate 
    opened by Riizade 2
  • bevy lyon 2dDebug Stage Conflict

    bevy lyon 2dDebug Stage Conflict

    when using Heron 2dDebug feature flag, there is a conflict with a shapes stage that exist in bevy_prototype_lyon = "0.5.0"

    thread 'main' panicked at 'Stage already exists: Shape.',
    
    bug 
    opened by jakyle 0
  • Recommend using SI units

    Recommend using SI units

    @bit-garden rightfully explained here why it is important to not use the pixel as a unit, but rather meter* instead.

    *: it is not really about "meter", but rather using a unit for simulation so that object sizes are close to 1. So a game that simulates planetary bodies may use Mm, and a game at a microscopic scale may better use µm.

    But that is not so intuitive for users who just start with heron, and they can encounter strange behavior (like #276).

    So, here is what we should do to improve heron in this area:

    • [ ] Update documentation to recommend using SI units as well as discourage using pixel as a unit
    • [ ] Update heron examples to follow that recommendation and show how to use a different unit-scale for the physics than pixels
    • [ ] Provide a metric-scale resource, so that heron automatically translates the pixel-unit of transforms into meters in the rapier simulation (something inspired by bevy_rapier's solution)
    documentation enhancement examples 
    opened by jcornaz 1
Releases(v5.0.2)
Owner
Jonathan Cornaz
Loving Kotlin, Rust and Elm
Jonathan Cornaz
Game physics in one weekend with bevy

Game Physics in a Weekend (in Rust) This project is an implementation of the Game Physics in a Weekend book using the Rust programming language and th

Cameron Hart 28 Dec 23, 2022
A physics lib for the bevy game engine based on physme

physimple Physimple aims to be the simplest(and capable) physics engine(currently for bevy) WARNING Beware for breaking changes with each update for n

null 24 Oct 28, 2022
Verlet physics plugin for bevy.

bevy_verlet Simple Verlet points and sticks implementation for bevy. Features You can simply add a VerletPoint component on any entity with a Transfor

Félix Lescaudey de Maneville 34 Dec 9, 2022
2D and 3D physics engine based on Extended Position Based Dynamics for Bevy.

Bevy XPBD Bevy XPBD is a 2D and 3D physics engine based on Extended Position Based Dynamics (XPBD) for the Bevy game engine. Design Below are some of

Joona Aalto 203 Jul 6, 2023
Just when you thought Bevy couldn't get more ergonomic, Bvy shows up to change the game.

Just when you thought Bevy couldn't get more ergonomic, Bvy shows up to change the game. Is this a joke? You decide. Does it work? You can bet your As

Carter Anderson 40 Oct 28, 2022
A simple camera for properly displaying tile-based low resolution pixel perfect 2D games in bevy.

Bevy Tiled Camera A simple camera for properly displaying low resolution pixel perfect 2D games in bevy. The camera will adjust the viewport to scale

sark 10 Oct 5, 2022
A framework for building adventure games in Bevy.

Bevy_adventure A framework for building 3d adventure games in Bevy. preview.mp4 Features Interactive trait is the backbone of the framework, allowing

Hank Jordan 9 Jan 5, 2023
Bevy virtual Joystick for mobile games (Works with mouse on desktop)

Bevy Virtual Joystick Create and use a Virtual Joystick in a UI for bevy Game Engine. Versions Aviable and compatible versions bevy VirtualJoystick 0.

Sergio Alejandro Ribera Costa 7 Apr 16, 2023
Explicitly set sprite layers for sprites in Bevy games.

extol_sprite_layer lets you specify the drawing order for sprites in your Bevy game using a separate component rather than via the z-coordinate of you

Ash 5 May 2, 2023
Atomic Physics Library

Iridium Atomic Physics Library Attempt at making a atomic database. Uses Nubase2020, ENSDF for decay chains, atomic masses, and half-lives. Nubase2020

J.A Sory 14 Jun 19, 2022
2 and 3-dimensional rigid body physics engine for Rust.

Users guide | 2D Documentation | 3D Documentation | Forum ⚠️ **This crate is now passively-maintained. It is being superseded by the Rapier project.**

dimforge 1.6k Jan 6, 2023
Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita

Sandbox Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita. It's also a precursor for an ongoing game project. Sandb

Okko Hakola 76 Nov 3, 2022
Little 2D physics engine used for my game Crate Before Attack.

Circle2D Circle2D is a little physics library used for my game CrateBeforeAttack. Live demo: https://koalefant.github.io/circle2d/ It is not productio

Evgeny Andreeshchev 24 Jan 14, 2022
Reimplementation of Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL

ten-minute-physics-rs reimplements Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL. Compared with the source pure Javascript im

Lucas V. Schuermann 56 Jan 26, 2023
A networked (p2p), cross-platform physics simulation example using rollback netcode

bevy_gaff (work in progress) bevy_gaff is an attempt at making a networked (p2p), cross-platform physics simulation using rollback netcode. It synchro

Johan Klokkhammer Helsing 13 Sep 5, 2023
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy

Bevy Voxel Cone Tracing bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy. Bevy Version

研究社交 208 Dec 27, 2022
A simple extension for `bevy-editor-pls` to support tilemap editing right inside the bevy app.

What is this This is a simple tilemap editor plugin, that hooks right into bevy_editor_pls to work with bevy_ecs_tilemap. It works completely within i

null 3 May 8, 2023
Bevy Simple Portals is a Bevy game engine plugin aimed to create portals.

Portals for Bevy Bevy Simple Portals is a Bevy game engine plugin aimed to create portals. Those portals are (for now) purely visual and can be used t

Sélène Amanita 11 May 28, 2023