Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

Force

A force and a torque a rigid body carries, applied by every physics step until the component changes or goes: a thruster, a rotor, a propeller, a fan, a hover pad, a jet pack, a constant wind on a sail, a magnet's pull, a conveyor that pushes. The step itself applies it: each step evaluates the force from the pose the body starts that step at, so it acts on the step it is meant for at any tick rate and any frame rate.

The force drives the body of its entity, or of the nearest ancestor holding one, so a body carries any number of forces through the entities under it: a rocket part with three thruster entities under it carries three, each acting where its entity stands on the part. One entity carries several Force components as well, each further one added under a name of its own (craft.component.add("Force", { name = "padBack", ... }), removed with craft.component.remove("Force", "padBack")); each acts from that entity's frame.

A force moves a dynamic body. A static or kinematic body carries its forces unmoved, and the log names each Force on one once; Physics.forces(id).applied reads whether this engine's step applies them.

Public fields:

  • force (newtons) and torque (newton-metres), stated in space: "local" (default: this entity's own frame, so the direction turns with the body) or "world" (fixed however the body turns).
  • point (default this entity's origin) in pointSpace: "local" (default: this entity's own space, scale included, moving with the body) or "world" (a point fixed in the world). A force acting off the centre of mass turns the body by the torque its offset makes.
  • throughCenterOfMass (default false): the force pushes through the centre of mass and turns nothing, wherever point is.
  • scale (default 1): a factor on the force and the torque, saved with the scene (a trim, a fixed thrust).
  • scaleValue (default ""): a named value (values.set) on this entity or an ancestor whose number multiplies the force and the torque too; a name no entity on that chain holds scales them to 0. One throttle value on a vehicle drives every thruster under it, read by the step with no script copying it. A named value is live runtime state and is never saved with the scene, so a starting throttle is written when the game starts (a component's awake).

Disabling the component (.enabled = false) switches the force off from the next step. The fields sync like every component field, and the peer simulating the body applies the force, so every peer sees the same motion: another peer holds the body as a replica that moves as the simulating peer's step moves it. A named value the force follows is read on the simulating peer, so the body's owner writes the throttle, and a replicate rate on it (values.declare) lets the other peers read the same throttle. Physics.forces(id) reads which forces act on a body, each at its current world value with the entity and instance name it comes from, and their sum.

-- hold a 10 kg crate up against gravity
crate.component.add("Force", { force = { 0, 98.1, 0 }, space = "world" })

-- a rocket: two thruster entities under the hull, each pushing along its own +Y
for _, x in { -1, 1 } do
    local t = entity.spawn("thruster", { parent = hull, position = { x, -2, 0 } })
    t.component.add("Force", { force = { 0, 600, 0 }, scaleValue = "throttle" })
end
hull.values.set("throttle", 0.8)

-- a constant wind on a sail
sail.component.add("Force", { force = { 12, 0, 0 }, space = "world" })

-- a hovercraft: a pad pushing world-up at each of two corners, both on the craft entity
craft.component.add("Force", { force = { 0, 150, 0 }, space = "world", point = { 1, 0, 1 } })
craft.component.add("Force", { name = "padBack", force = { 0, 150, 0 }, space = "world", point = { -1, 0, -1 } })