跳转到内容

物理 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 相同:

字段类型说明
entityEntity被碰撞的实体
pointVec2世界像素坐标的接触点
normalVec2接触处的表面法线
fractionnumber平移距离上的碰撞分数(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);

参见