bevy_xpbd
bevy_xpbd copied to clipboard
Low mass joint with angle limits unstable
trafficstars
Only tested in 2D
bevy = "0.17.2"
avian2d = "0.4.1"
https://github.com/user-attachments/assets/624a8de7-f346-4977-9715-7353fb03c8a3
- Decreasing the
SubstepCountimproves the situation - Increasing the
Massimproves the situation but even with 0.1 (100g) it stays unstable - When the mass goes even lower (0.0001) the angle limits are no longer respected.
use avian2d::{math::*, prelude::*};
use bevy::color::palettes::css;
use bevy::prelude::*;
#[derive(Component)]
struct Flipper;
fn main() {
App::new()
.add_plugins((DefaultPlugins, PhysicsPlugins::default()))
.insert_resource(SubstepCount(50))
.insert_resource(Gravity(Vector::NEG_Y * 9.81))
.add_systems(Startup, setup)
.add_systems(Update, keyboard_control)
.run();
}
const FLIPPER_LENGTH: f32 = 0.071;
const FLIPPER_WIDTH: f32 = 0.018;
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
// we model a pinball flipper in actual size
commands.spawn((
Camera2d,
Projection::Orthographic(OrthographicProjection {
scale: 0.0002,
..OrthographicProjection::default_2d()
}),
));
let anchor = commands
.spawn((
Mesh2d(meshes.add(Mesh::from(Circle::new(0.002)))),
MeshMaterial2d(materials.add(ColorMaterial::from(Color::from(css::YELLOW)))),
RigidBody::Static,
Transform::from_xyz(0.0, 0.0, 1.0),
))
.id();
let flipper = commands
.spawn((
Flipper,
Mesh2d(meshes.add(Mesh::from(Rectangle::new(FLIPPER_LENGTH, FLIPPER_WIDTH)))),
MeshMaterial2d(materials.add(ColorMaterial::from(Color::from(css::TEAL)))),
RigidBody::Dynamic,
Mass::from(0.01), // 10g
Collider::rectangle(FLIPPER_LENGTH, FLIPPER_WIDTH),
AngularDamping::from(10.0),
))
.id();
commands.spawn(
RevoluteJoint::new(anchor, flipper)
.with_local_anchor1(Vec2::ZERO)
.with_local_anchor2(Vec2::new(-FLIPPER_LENGTH / 2.0, 0.0))
.with_angle_limits((-30.0f32).to_radians(), (30.0f32).to_radians()),
);
}
fn keyboard_control(
keyboard_input: Res<ButtonInput<KeyCode>>,
flippers: Query<Entity, With<Flipper>>,
mut commands: Commands,
) {
for entity in flippers.iter() {
if keyboard_input.pressed(KeyCode::ShiftLeft) {
commands.entity(entity).insert(ConstantTorque(0.05));
} else if keyboard_input.pressed(KeyCode::ShiftRight) {
commands.entity(entity).insert(ConstantTorque(-0.05));
} else {
commands.entity(entity).remove::<ConstantTorque>();
}
}
}