跳到主要内容

关节

Alpha 阶段

关节组件处于 Alpha 阶段,行为和 API 仍可能变化。所有开发方式都可通过代码使用,Web Components 提供标签,编辑器从 2.32 起提供检查器。PlayCanvas React 暂无对应组件。

关节约束两个刚体的相对运动,例如绕铰链摆动的门、滑轨上的抽屉、链条、弹簧上的箱子,以及受到足够冲击才断开的焊接积木塔。

关节

关节工作方式​

关节是独立实体上的 JointComponent,该实体自身不受约束。其世界变换定义关节坐标系:位置为锚点,局部 X 为主轴。铰链绕 X 旋转,滑块沿 X 平移,球关节绕 X 扭转。旋转关节实体即可调整方向。

通过 entityA 和 entityB 指定两个刚体,均需有刚体组件。entityB 留空可将 A 约束到世界固定点。常见做法是将关节实体作为 A 的子实体放在支点上,使支点随所属部件移动。

两个容易误解的细节:

  • 关节坐标系只捕获一次,发生在约束创建时,通常是组件启用且两刚体均进入模拟时。之后移动关节实体无效,需调用 refreshFrames(),从当前变换重新捕获。与刚体一样,全程忽略实体缩放。
  • 限位从初始姿态计量,并非关节实体的绝对角度。约束创建时两个关节坐标系重合,各自由度都为零。铰链 0 到 110 度表示从刚体初始位置再转最多 110 度,而非绝对角度。

关节类型​

type 选择约束类型,也决定哪些属性有效:

类型常量约束使用属性
fixedJOINTTYPE_FIXED将两个刚体刚性固定在一起无
ballJOINTTYPE_BALL球窝关节,绕锚点自由旋转,可限制摆动与扭转swingLimitY, swingLimitZ, twistLimit
hingeJOINTTYPE_HINGE绕关节坐标系 X 轴旋转,可设置限位和马达limits, motorSpeed, maxMotorForce
sliderJOINTTYPE_SLIDER沿关节坐标系 X 轴平移,可设置限位和马达limits, motorSpeed, maxMotorForce
6dofJOINTTYPE_6DOF各线性与旋转轴独立设为锁定、限位或自由,可配置弹簧linearMotionX/Y/Z, angularMotionX/Y/Z, linearLimitsX/Y/Z, angularLimitsX/Y/Z, linearStiffness, angularStiffness, linearDamping, angularDamping, linearEquilibrium, angularEquilibrium

所有类型都支持 enableCollision,决定两刚体是否仍相互碰撞,默认关闭;也都支持 breakImpulse。

6dof 各轴默认 MOTION_LOCKED,因此不设置其他内容时类似固定关节。用 MOTION_FREE 或 MOTION_LIMITED 开放需要的轴,为限位轴设置对应范围,再将刚度设为正数,即可成为拉向平衡位置的弹簧。

添加关节​

下面将动态门通过铰链约束到静态门框。关节实体位于铰链线上,旋转使局部 X 向上,0 到 110 度限位让门只能单向打开:

const hinge = new pc.Entity('hinge');
hinge.setPosition(1, 1, 0);
hinge.setEulerAngles(0, 0, 90); // the local X axis now points up
hinge.addComponent('joint', {
type: pc.JOINTTYPE_HINGE,
entityA: door,
entityB: doorFrame,
enableLimits: true,
limits: new pc.Vec2(0, 110)
});
app.root.addChild(hinge);

pc.Application 自动注册关节系统。使用 pc.AppBase 时,在 AppOptions.componentSystems 中除碰撞和刚体系统外,还需加入 pc.JointComponentSystem。

马达、限位与断裂​

限位需要同时启用 enableLimits 并设置限位值。只设置 limits、但 enableLimits 为 false 的铰链仍可自由旋转。

铰链和滑块支持马达。maxMotorForce 大于零时启用,以 motorSpeed 驱动。铰链单位为度/秒,滑块为单位/秒。启用限位时,马达到达限位会停止推进。

// A windmill: spin the rotor about the hinge axis at 90 degrees per second
hinge.joint.motorSpeed = 90;
hinge.joint.maxMotorForce = 100;

所有关节都可断裂。breakImpulse 指定失效冲量,默认 Infinity 表示不断裂。断裂时触发 break,isBroken 变为 true,两刚体独立运动。调用 refreshFrames() 可按当前变换重新连接。

const weld = jointEntity.joint;
weld.breakImpulse = 60;
weld.on('break', () => {
console.log('The weld snapped');
});
备注

如果 ammo.js 构建未暴露约束状态,则不能检测 6dof 断裂,也不会触发该类型的 break。其他关节不受影响。

另请参阅​

  • JointComponent:全部关节属性 API。
  • <pc-joint>:Web Components 中的相同关节及各类型实时示例。
  • Ragdoll:通过球关节和铰链构建角色的引擎示例。
  • 刚体:关节约束的对象。
  • Joint 组件:对应编辑器检查器。