AnvilKitAnvilKit

物理系统

内置 AABB 物理和 Rapier 3D 集成

物理系统演示

AnvilKit 提供两种物理方案:轻量级的内置 AABB 系统(默认)和通过 rapier3d 实现的完整刚体模拟(需启用 feature)。

v0.3 模块重构

在 v0.3 中,物理模块从单个 physics.rs 文件拆分为 physics/ 目录,以更好地组织代码:

  • physics/mod.rs -- 重导出(导入路径保持不变)
  • physics/components.rs -- VelocityAabbColliderRigidBodyCollider
  • physics/aabb.rs -- AABB 碰撞检测逻辑
  • physics/rapier.rs -- Rapier 集成系统
  • physics/events.rs -- CollisionEvent 和事件提取

通过 mod.rs 中的重导出,导入路径保持不变,现有代码不受影响。

数学工具

Aabb 和射线投射工具现在也可以从 anvilkit_core::math 获取(从渲染 crate 移出),无 GPU 依赖:

  • anvilkit_core::math::Aabb -- 纯数学 AABB,无 GPU 依赖
  • anvilkit_core::math::raycast -- screen_to_rayray_plane_intersectionray_sphere_intersection

内置 AABB 物理(默认)

PhysicsPluginUpdate 中注册速度积分和 N-平方 AABB 碰撞检测。

类型类别说明
DeltaTimeResource帧间隔时间(秒)— 由 update_delta_time_system 自动从 Time 同步
VelocityComponentlinear: Vec3, angular: Vec3
AabbColliderComponenthalf_extents: Vec3
CollisionEventsResource已弃用 -- 请改用 EventWriter<CollisionEvent> / EventReader<CollisionEvent>
CollisionEventStructa: Entity, b: Entity
系统说明
update_delta_time_system从核心 Time 资源同步 DeltaTime(在 PreUpdate 中注册)
velocity_integration_systemtransform.translation += velocity.linear * dt
collision_detection_systemN-平方 AABB 重叠检测(缩放感知),写入 CollisionEvents

推荐调度

物理系统应在 FixedUpdate 中运行以实现确定性模拟:

app.add_systems(AnvilKitSchedule::FixedUpdate, (
    velocity_integration_system,
    collision_detection_system.after(velocity_integration_system),
));

FixedUpdate 以固定 1/60s 时间步长运行(可通过 app.set_fixed_timestep() 配置),独立于帧率。确保不同硬件上的物理行为一致。

use anvilkit::prelude::*;

fn setup_physics(mut commands: Commands) {
    // 动态移动方块
    commands.spawn((
        Transform::from_xyz(0.0, 10.0, 0.0),
        Velocity::linear(Vec3::new(0.0, -5.0, 0.0)),
        AabbCollider::cube(0.5),
    ));

    // 静态地面
    commands.spawn((
        Transform::from_xyz(0.0, 0.0, 0.0),
        AabbCollider::new(Vec3::new(50.0, 0.1, 50.0)),
    ));
}

fn read_collisions(mut events: EventReader<CollisionEvent>) {
    for event in events.read() {
        log::info!("Hit: {:?} <-> {:?}", event.a, event.b);
    }
}

Rapier 集成(feature "rapier"

启用 rapier feature 以使用 rapier3d 进行完整的刚体模拟。

RapierPhysicsPluginUpdate 中注册四个系统:

系统顺序说明
sync_to_rapier_system第 1从 ECS 的 RigidBody+Collider+Transform 创建 rapier 刚体
step_physics_system第 2推进 rapier 模拟一个 tick
sync_from_rapier_system第 3将 rapier 位置写回 ECS 的 Transform
extract_collision_events_system第 3从 rapier 窄相检测填充 CollisionEvents
类型说明
RapierContext持有所有 rapier 状态的 Resource(刚体集合、碰撞体集合、管线等)
RigidBodyComponent:body_typemassgravity_scaleis_sensor、damping
ColliderComponent:shape(Sphere/Cuboid/Capsule/TriMesh)、frictionrestitution
RaycastHit结果结构体:entitypointnormaldistance
use anvilkit::prelude::*;

fn setup_rapier(mut commands: Commands) {
    // 动态球体
    commands.spawn((
        Transform::from_xyz(0.0, 10.0, 0.0),
        RigidBody::dynamic(),
        Collider::sphere(0.5),
        Velocity::default(),
    ));

    // 静态地面
    commands.spawn((
        Transform::default(),
        RigidBody::fixed(),
        Collider::cuboid(Vec3::new(50.0, 0.1, 50.0)),
    ));
}

// 射线查询
fn shoot_ray(ctx: Res<RapierContext>) {
    if let Some(hit) = ctx.raycast(
        Vec3::new(0.0, 5.0, 0.0), // 起点
        Vec3::NEG_Y,               // 方向
        100.0,                     // 最大距离
    ) {
        log::info!(
            "Hit entity {:?} at {} (distance {})",
            hit.entity, hit.point, hit.distance
        );
    }
}

目录