# JointComponent

Class · extends [`Component`](https://api.playcanvas.com/engine/classes/Component.md) · category: Physics

Source: https://github.com/playcanvas/engine/blob/970d89f6d3bc6667f4e1f88153abd6e7e82ed52c/src/framework/components/joint/component.js#L110

The JointComponent constrains the relative motion of two rigid bodies. The entity holding the
joint component is not itself constrained - instead, its world transform defines the joint
frame: the anchor point and axes that the constraint operates about. The constrained bodies are
assigned via [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya) and [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb), both of which must have a
[RigidBodyComponent](https://api.playcanvas.com/engine/classes/RigidBodyComponent.md). If [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb) is null, [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya) is constrained to a
fixed point in world space.

A joint's primary axis is the joint entity's local X axis: a hinge rotates about X, a slider
translates along X and a ball joint twists about X. To aim a joint, rotate the joint entity. A
common pattern is to parent the joint entity to [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya) at the pivot point.

The joint frames are captured when the underlying constraint is created - typically when the
component is enabled and both bodies are present in the physics simulation. Moving the joint
entity afterwards has no effect on an existing constraint. Call [refreshFrames](https://api.playcanvas.com/engine/classes/JointComponent.md#refreshframes) to
re-capture the frames from the current world transforms. Entity scale is ignored, matching the
behavior of rigid bodies.

At creation the two joint frames coincide, so every degree of freedom reads zero: limits and
equilibrium values are measured from the initial relative pose of the two bodies, not from the
joint entity's transform or any absolute separation. Linear degrees of freedom are positive
when [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb) (or the world anchor when [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb) is null) moves along the
joint's positive axes relative to [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya). Angular degrees of freedom measure the
opposite body: they are positive when [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya) rotates counter-clockwise about the
joint's axes relative to [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb) or the world anchor, viewed from each axis's positive
end (right-handed). In the door hinge example below, the limits of `[0, 110]` let the door
swing counter-clockwise, viewed from above, up to 110 degrees from its starting pose.

Many properties apply only to specific joint types; each one documents the types it affects,
and properties without such a note (for example [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya), [enableCollision](https://api.playcanvas.com/engine/classes/JointComponent.md#enablecollision) and
[breakImpulse](https://api.playcanvas.com/engine/classes/JointComponent.md#breakimpulse)) apply to all types.

To add a JointComponent to an [Entity](https://api.playcanvas.com/engine/classes/Entity.md), use [Entity#addComponent](https://api.playcanvas.com/engine/classes/Entity.md#addcomponent):

```javascript
// Create a door hinge: the joint entity's position is the hinge point and its
// local X axis (rotated here to point up) is the hinge axis
const hinge = new Entity('hinge');
hinge.setPosition(1, 1, 0);
hinge.setEulerAngles(0, 0, 90);
hinge.addComponent('joint', {
    type: JOINTTYPE_HINGE,
    entityA: door,
    entityB: doorFrame,
    enableLimits: true,
    limits: new Vec2(0, 110)
});
app.root.addChild(hinge);
```

## Accessors

### angularDamping

```ts
get angularDamping(): Vec3
set angularDamping(arg: Vec3)
```

### angularEquilibrium

```ts
get angularEquilibrium(): Vec3
set angularEquilibrium(arg: Vec3)
```

### angularLimitsX

```ts
get angularLimitsX(): Vec2
set angularLimitsX(arg: Vec2)
```

### angularLimitsY

```ts
get angularLimitsY(): Vec2
set angularLimitsY(arg: Vec2)
```

### angularLimitsZ

```ts
get angularLimitsZ(): Vec2
set angularLimitsZ(arg: Vec2)
```

### angularMotionX

```ts
get angularMotionX(): "free" | "limited" | "locked"
set angularMotionX(arg: "free" | "limited" | "locked")
```

### angularMotionY

```ts
get angularMotionY(): "free" | "limited" | "locked"
set angularMotionY(arg: "free" | "limited" | "locked")
```

### angularMotionZ

```ts
get angularMotionZ(): "free" | "limited" | "locked"
set angularMotionZ(arg: "free" | "limited" | "locked")
```

### angularStiffness

```ts
get angularStiffness(): Vec3
set angularStiffness(arg: Vec3)
```

### breakImpulse

```ts
get breakImpulse(): number
set breakImpulse(impulse: number)
```

### enableCollision

```ts
get enableCollision(): boolean
set enableCollision(enableCollision: boolean)
```

### enableLimits

```ts
get enableLimits(): boolean
set enableLimits(arg: boolean)
```

### entityA

```ts
get entityA(): Entity | null
set entityA(arg: Entity | null)
```

### entityB

```ts
get entityB(): Entity | null
set entityB(arg: Entity | null)
```

### isBroken

```ts
get isBroken(): boolean
```

### limits

```ts
get limits(): Vec2
set limits(arg: Vec2)
```

### linearDamping

```ts
get linearDamping(): Vec3
set linearDamping(arg: Vec3)
```

### linearEquilibrium

```ts
get linearEquilibrium(): Vec3
set linearEquilibrium(arg: Vec3)
```

### linearLimitsX

```ts
get linearLimitsX(): Vec2
set linearLimitsX(arg: Vec2)
```

### linearLimitsY

```ts
get linearLimitsY(): Vec2
set linearLimitsY(arg: Vec2)
```

### linearLimitsZ

```ts
get linearLimitsZ(): Vec2
set linearLimitsZ(arg: Vec2)
```

### linearMotionX

```ts
get linearMotionX(): "free" | "limited" | "locked"
set linearMotionX(arg: "free" | "limited" | "locked")
```

### linearMotionY

```ts
get linearMotionY(): "free" | "limited" | "locked"
set linearMotionY(arg: "free" | "limited" | "locked")
```

### linearMotionZ

```ts
get linearMotionZ(): "free" | "limited" | "locked"
set linearMotionZ(arg: "free" | "limited" | "locked")
```

### linearStiffness

```ts
get linearStiffness(): Vec3
set linearStiffness(arg: Vec3)
```

### maxMotorForce

```ts
get maxMotorForce(): number
set maxMotorForce(arg: number)
```

### motorSpeed

```ts
get motorSpeed(): number
set motorSpeed(arg: number)
```

### swingLimitY

```ts
get swingLimitY(): number
set swingLimitY(arg: number)
```

### swingLimitZ

```ts
get swingLimitZ(): number
set swingLimitZ(arg: number)
```

### twistLimit

```ts
get twistLimit(): number
set twistLimit(arg: number)
```

### type

```ts
get type(): "fixed" | "ball" | "hinge" | "slider" | "6dof"
set type(type: "fixed" | "ball" | "hinge" | "slider" | "6dof")
```

## Methods

### onBeforeRemove

```ts
onBeforeRemove(): void
```

### refreshFrames

```ts
refreshFrames(): void
```

Destroys and recreates the underlying constraint, re-capturing the joint frames from the
current world transforms of the joint entity, [entityA](https://api.playcanvas.com/engine/classes/JointComponent.md#entitya) and [entityB](https://api.playcanvas.com/engine/classes/JointComponent.md#entityb). Call
this after moving the joint entity to re-anchor the joint, or to re-attach a joint that has
broken.

## Events

### EVENT_BREAK

```ts
static EVENT_BREAK: string = 'break'
```

Fired when the applied impulse on the joint exceeds [breakImpulse](https://api.playcanvas.com/engine/classes/JointComponent.md#breakimpulse) and the constraint
breaks. The broken joint no longer constrains its bodies and [isBroken](https://api.playcanvas.com/engine/classes/JointComponent.md#isbroken) becomes true.
Call [refreshFrames](https://api.playcanvas.com/engine/classes/JointComponent.md#refreshframes) to re-attach it. Note that on ammo builds that expose no
constraint state, breakage of 6dof joints cannot be detected, so this event does not fire
for them - other joint types are unaffected.

**Example**

```ts
entity.joint.on('break', () => {
    console.log('The joint broke');
});
```

## Inherited from [Component](https://api.playcanvas.com/engine/classes/Component.md)

- `entity: Entity`
- `system: ComponentSystem`
- `get enabled(): boolean` · `set enabled(value: boolean)`
- `fire(name: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any, arg6?: any, arg7?: any, arg8?: any): EventHandler`
- `hasEvent(name: string): boolean`
- `off(name?: string, callback?: HandleEventCallback, scope?: any): EventHandler`
- `on(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
- `once(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
