跳转到内容

物理

物理系统提供基于独立 Box2D WASM 模块的 2D 刚体模拟。编辑器和构建流程会自动处理模块加载——你只需在设置中启用物理并为实体添加组件。

设置

在编辑器中启用物理:Settings → Physics → Enable Physics

在同一面板中配置模拟参数:

设置项默认值说明
Gravity X0水平重力
Gravity Y-9.81垂直重力(负数 = 向下)
Fixed Timestep1/60物理步进间隔(秒)
Sub-Step Count4每次物理步进的子步数,用于提高精度

坐标转换 (PPU)

碰撞体尺寸(halfExtentsradiushalfHeight)以**物理单位(米)**设定。Canvas 组件的 pixelsPerUnit(默认 100)决定像素坐标与物理坐标之间的换算比例。

位置转换自动完成——实体位置(像素)在发送到 Box2D 时除以 PPU,读回时乘以 PPU。Physics API 的值(forcevelocityimpulsegravity)同样使用物理单位,无需手动换算。

组件

在场景编辑器中将物理组件与 LocalTransform 一起添加到实体上。

RigidBody

每个物理实体都需要 RigidBody 组件,定义刚体类型和物理属性。

属性类型默认值说明
bodyTypenumber2(Dynamic)0=静态,1=运动学,2=动态
gravityScalenumber1.0重力倍率
linearDampingnumber0.0线速度阻尼
angularDampingnumber0.0角速度阻尼
fixedRotationbooleanfalse锁定旋转
bulletbooleanfalse高速物体连续碰撞检测
enabledbooleantrue启用物理刚体

碰撞体

每个实体还需要一个碰撞体形状,选择其一:

  • BoxColliderhalfExtents(Vec2)、offset(Vec2)、densityfrictionrestitutionisSensor
  • CircleColliderradiusoffset(Vec2)、densityfrictionrestitutionisSensor
  • CapsuleColliderradiushalfHeightoffset(Vec2)、densityfrictionrestitutionisSensor

详见组件完整属性表。

刚体类型

Static(0)

不移动。用于墙壁、地面和平台。

rigidBody.bodyType = 0;

Kinematic(1)

通过代码(变换)移动,不受物理力影响。其他刚体会与之碰撞但不会推动它。用于移动平台和电梯。

rigidBody.bodyType = 1;

Dynamic(2)

完全模拟。响应重力、力和碰撞。用于玩家、投射物和物理对象。

rigidBody.bodyType = 2;

碰撞事件

PhysicsEvents 资源读取碰撞和传感器事件:

import { defineSystem, addSystem, Res } from 'esengine';
import { PhysicsEvents } from 'esengine/physics';
addSystem(defineSystem(
[Res(PhysicsEvents)],
(events) => {
for (const e of events.collisionEnters) {
// e.entityA, e.entityB, e.normalX, e.normalY, e.contactX, e.contactY
}
for (const e of events.collisionExits) {
// e.entityA, e.entityB
}
for (const e of events.sensorEnters) {
// e.sensorEntity, e.visitorEntity
}
for (const e of events.sensorExits) {
// e.sensorEntity, e.visitorEntity
}
}
));

示例:简单平台跳跃

在编辑器中设置地面、玩家和金币传感器,然后用代码处理事件:

import { defineSystem, addSystem, Res, Input, Query, Mut, LocalTransform } from 'esengine';
import { RigidBody, PhysicsEvents } from 'esengine/physics';
import { Player, Coin } from './components';
addSystem(defineSystem(
[Res(PhysicsEvents)],
(events) => {
for (const e of events.sensorEnters) {
// 金币收集
}
}
));

编辑器设置:

  • 地面LocalTransform + RigidBody(bodyType=0 Static)+ BoxCollider(halfExtents={x:10, y:0.5})+ Sprite
  • 玩家LocalTransform + RigidBody(bodyType=2 Dynamic,fixedRotation=true)+ BoxCollider + Sprite + Player 标签
  • 金币LocalTransform + RigidBody(bodyType=0 Static)+ CircleCollider(isSensor=true)+ Sprite + Coin 标签

Physics API(进阶)

Physics 类提供运行时力/速度控制。物理插件加载完成后会自动注册 PhysicsAPI 资源,可在任何系统中通过 Res(PhysicsAPI) 访问:

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)

下一步