物理 API
Physics 类提供运行时力/速度控制。物理插件加载完成后会自动注册 PhysicsAPI 资源,可在任何系统中通过 Res(PhysicsAPI) 访问。
访问 API
import { defineSystem, addSystem, Res } from 'esengine';import { PhysicsAPI } from 'esengine/physics';
addSystem(defineSystem( [Res(PhysicsAPI)], (physics) => { physics.applyForce(entity, { x: 0, y: 10 }); }));方法
| 方法 | 说明 |
|---|---|
applyForce(entity, force) | 施加持续力(Vec2) |
applyImpulse(entity, impulse) | 施加瞬时冲量(Vec2) |
setLinearVelocity(entity, velocity) | 直接设置线速度 |
getLinearVelocity(entity) | 获取当前线速度(Vec2) |
setAngularVelocity(entity, omega) | 设置角速度(number) |
getAngularVelocity(entity) | 获取当前角速度 |
applyTorque(entity, torque) | 施加旋转扭矩 |
applyAngularImpulse(entity, impulse) | 施加瞬时角冲量 |
setGravity(gravity) | 运行时修改世界重力 |
getGravity() | 获取当前世界重力(Vec2) |
shapeCastCircle(center, radius, translation, maskBits?) | 扫过圆形并返回碰撞结果 |
shapeCastBox(center, halfExtents, angle, translation, maskBits?) | 扫过带旋转矩形并返回碰撞结果 |
shapeCastCapsule(center1, center2, radius, translation, maskBits?) | 扫过胶囊体并返回碰撞结果 |
overlapAABB(min, max, maskBits?) | 查询与 AABB 重叠的实体 |
getMass(entity) | 获取刚体质量(kg) |
getInertia(entity) | 获取刚体转动惯量 |
getCenterOfMass(entity) | 获取刚体质心位置(Vec2,像素) |
getMassData(entity) | 获取质量、惯量和质心 |
力 vs 冲量
- 力每帧持续施加。效果取决于刚体质量,在物理时间步中积分。适用于持续推力(如火箭推进、风力)。
- 冲量瞬间施加。直接改变速度,与帧率无关。适用于一次性事件(如跳跃、爆炸击退)。
形状投射
v0.12.0 新增。
形状投射沿平移向量扫过一个形状并返回所有碰撞。类似射线检测但有体积,适用于判断角色能否通过缝隙或预测沿路径的碰撞。
每个方法返回 ShapeCastHit[],结构与 RaycastHit 相同:
| 字段 | 类型 | 说明 |
|---|---|---|
entity | Entity | 被碰撞的实体 |
point | Vec2 | 世界像素坐标的接触点 |
normal | Vec2 | 接触处的表面法线 |
fraction | number | 平移距离上的碰撞分数(0..1) |
// 圆形投射:从 center 沿 translation 扫过圆形const hits = physics.shapeCastCircle( center, // Vec2 — 起点 radius, // number — 圆形半径(像素) translation, // Vec2 — 扫过方向与距离(像素) maskBits, // number — 碰撞层掩码(默认 0xFFFF));
// 矩形投射:扫过带旋转的矩形const hits = physics.shapeCastBox( center, // Vec2 — 矩形中心 halfExtents, // Vec2 — 半宽/半高(像素) angle, // number — 旋转角度(弧度) translation, // Vec2 — 扫过向量(像素) maskBits,);
// 胶囊投射:扫过由两个圆心 + 半径定义的胶囊体const hits = physics.shapeCastCapsule( center1, // Vec2 — 第一个圆心 center2, // Vec2 — 第二个圆心 radius, // number — 胶囊半径(像素) translation, // Vec2 — 扫过向量(像素) maskBits,);AABB 重叠查询
v0.12.0 新增。
查询所有碰撞体与轴对齐包围盒重叠的实体:
const entities = physics.overlapAABB( { x: 100, y: 100 }, // 最小角(像素) { x: 300, y: 300 }, // 最大角(像素) 0xFFFF, // 碰撞层掩码);for (const entity of entities) { // entity 与 AABB 重叠}返回去重后的 Entity[]。
质量数据
v0.12.0 新增。
在运行时读取刚体的质量属性:
// 单独查询const mass = physics.getMass(entity); // number(kg)const inertia = physics.getInertia(entity); // number(kg*px^2)const center = physics.getCenterOfMass(entity); // Vec2(像素)
// 一次获取全部const data = physics.getMassData(entity);// { mass: number, inertia: number, centerOfMass: Vec2 }关节状态查询
v0.12.0 新增。
Distance、Prismatic、Wheel 关节的运行时状态控制。
Distance 关节
// 查询const length = physics.getDistanceJointLength(entity); // 静止长度(px)const current = physics.getDistanceJointCurrentLength(entity); // 当前长度(px)const force = physics.getDistanceJointMotorForce(entity);
// 修改physics.setDistanceJointLength(entity, 200);physics.enableDistanceJointSpring(entity, true);physics.enableDistanceJointLimit(entity, true);physics.setDistanceJointLimits(entity, 100, 300); // 最小、最大(px)physics.enableDistanceJointMotor(entity, true);physics.setDistanceJointMotorSpeed(entity, 50);physics.setDistanceJointMaxMotorForce(entity, 1000);Prismatic 关节
// 查询const translation = physics.getPrismaticJointTranslation(entity); // 当前偏移(px)const speed = physics.getPrismaticJointSpeed(entity); // 当前速度(px/s)const force = physics.getPrismaticJointMotorForce(entity);
// 修改physics.enablePrismaticJointSpring(entity, true);physics.enablePrismaticJointLimit(entity, true);physics.setPrismaticJointLimits(entity, -100, 100); // 下限、上限(px)physics.enablePrismaticJointMotor(entity, true);physics.setPrismaticJointMotorSpeed(entity, 80);physics.setPrismaticJointMaxMotorForce(entity, 500);Wheel 关节
// 查询const torque = physics.getWheelJointMotorTorque(entity);
// 修改physics.enableWheelJointSpring(entity, true);physics.enableWheelJointLimit(entity, true);physics.setWheelJointLimits(entity, -50, 50); // 下限、上限(px)physics.enableWheelJointMotor(entity, true);physics.setWheelJointMotorSpeed(entity, 60);physics.setWheelJointMaxMotorTorque(entity, 200);