跳到主要内容

移动刚体

动态刚体响应力和冲量。力在一段时间内作用,冲量瞬间改变速度。两者都由 RigidBodyComponent 提供,只影响动态刚体;静态不移动,运动学由你定位,因此调用无效。

本页所有操作都调用 rigidbody,各开发方式完全相同,区别只在代码运行位置。

运行物理代码​

按住按键时通常每帧施力,因此需要能够逐帧运行并访问实体的位置:

订阅应用 update,或按照脚本编程为实体附加脚本:

app.on('update', (dt) => {
// While the right arrow key is held, push the box along the world X axis
if (app.keyboard.isPressed(pc.KEY_RIGHT)) {
box.rigidbody.applyForce(10, 0, 0);
}
});

力​

持续推动重物时,应在推动期间持续施力。力累积到下一物理步,每帧施力产生持续加速度;相同力下,较重刚体加速更慢:

// Push along the world X axis, every frame while the push lasts
entity.rigidbody.applyForce(10, 0, 0);

冲量​

炮弹发射应施加一次冲量。冲量是动量的瞬间变化,因此只施加一次,而非每帧:

// Launch up and to the right, once
entity.rigidbody.applyImpulse(10, 10, 0);

两个方法都接受 Vec3,适合运行时计算方向:

// Launch the body along the direction it is facing
const impulse = entity.forward.clone().mulScalar(10);
entity.rigidbody.applyImpulse(impulse);

在指定点施加​

默认作用于质心,只改变速度,不使刚体旋转。传入可选作用点,可同时产生旋转。两个方法对点的解释不同:

  • applyForce(force, point):点是相对刚体位置的世界空间偏移。
  • applyImpulse(impulse, point):点位于实体局部空间。
// Impulse: the point is in the entity's local space, so this pushes up on the
// point 1 unit along the entity's local Z axis and makes the body tip over
entity.rigidbody.applyImpulse(new pc.Vec3(0, 10, 0), new pc.Vec3(0, 0, 1));

// Force: the point is a world space offset from the body, so transform the
// same local point into world space first
const offset = entity.getWorldTransform().transformVector(new pc.Vec3(0, 0, 1));
entity.rigidbody.applyForce(new pc.Vec3(0, 10, 0), offset);

也可传入六个数字,前三个为力或冲量,后三个为作用点。

扭矩​

让刚体旋转而不平移时,施加扭矩。applyTorque 对应持续力,applyTorqueImpulse 对应冲量。两者接受 Vec3 或三个数字,方向表示世界空间旋转轴,长度表示强度:

// Keep spinning the body about the world Y axis while called every frame
entity.rigidbody.applyTorque(0, 5, 0);

// Give the body a single kick of spin about the world X axis
entity.rigidbody.applyTorqueImpulse(2, 0, 0);

直接设置速度​

有时希望无论质量如何都以精确速度移动,例如角色立即达到最高速,或重置投射物。可直接赋值 linearVelocity 和 angularVelocity:

// Move at 5 units per second along the world X axis, keeping the current vertical speed
const velocity = entity.rigidbody.linearVelocity;
entity.rigidbody.linearVelocity = new pc.Vec3(5, velocity.y, 0);

// Stop all motion
entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
entity.rigidbody.angularVelocity = pc.Vec3.ZERO;

速度 getter 返回只读快照,原地修改返回向量无效,应始终赋新值。完整角色实现见引擎第一人称和第三人称控制器脚本。

运动学运动​

运动学刚体忽略力、冲量和速度。移动实体后,物理引擎在下一步开始读取新变换;站在运动学平台上的动态刚体会被带动:

// Slide a platform back and forth along the world X axis
let time = 0;
app.on('update', (dt) => {
time += dt;
platform.setPosition(Math.sin(time) * 2, 0.5, 0);
});
提示

阻尼与轴向系数影响上述行为。阻尼随时间减速,某轴系数为 0 则禁止该轴移动或旋转,可用于保持角色直立或限制到 2D 平面。

另请参阅​