Skip to content

Physics and joints ​

KHIM simulates parts on the game server (and in KHIM Engine's Play). One unit is one stud; gravity is 196.2 units/s², as in Roblox.

Anchored or loose ​

  • An anchored part stays exactly where it is. Floors, walls, buildings.
  • A loose part (anchored = false) falls, rolls, is pushed and knocked about. Crates, balls, debris.
lua
local crate = world.Crate
crate.anchored = false
crate:applyImpulse(vec3(0, 500, -300))   -- a shove, divided by its mass
crate.velocity = vec3(0, 50, 0)          -- or set its speed

Materials and mass ​

A part weighs its volume times its material's density, and its material sets how it grips and bounces:

MaterialDensityFrictionBounce
Plastic, Neon0.70.50.1
Smooth0.70.30.1
Wood0.350.60.05
Glass2.40.250.2
Metal7.80.40.05
Grass0.90.650.05
Brick1.90.750.05
Concrete2.40.70.03
Sand1.60.850
Rock2.70.650.05
Water1.00.10
Leaves0.30.60.02

So the same push moves a big Metal part much less than a small Wood one.

Collision groups ​

Every part is in one collision group (part.group, "Default" to start). Groups decide what passes through what:

lua
local door = world.VipDoor
door.group = "VipDoor"
physics.collide("VipDoor", "Players", false)   -- players walk through it; crates still bump into it

print(physics.collides("VipDoor", "Players"))  -- false
  • Built in: Default, Players (every character) and Ragdoll. A world can name 13 of its own (up to 23 characters each).
  • physics.collide(a, b, false) with a == b makes a group's parts pass through each other.
  • touched still fires for parts that don't collide, so the VIP door can still tell who went through.

In KHIM Engine you can set the table without code: a part's Inspector > Behavior > CollisionGroup > Which groups collide... (or Insert > Collision groups) - a grid of ticks.

Welds ​

A weld holds two parts together as one. KHIM Engine keeps welds between parts built together, and a Model's clone() keeps them. Welded parts don't collide with each other.

Joints ​

A joint goes in the part that moves and names the part it is joined to (part1):

JointDoesLike
HingeTurns about an axisA door, a wheel, a lever
SliderSlides along an axisA lift, a drawer, a piston
BallJointTurns every way about a pointA lamp on a chain
SpringPulls toward a rest lengthA car's suspension, a trampoline
RopeKeeps at most a length apartA swing, a crane's hook

In KHIM Engine: select the part it joins to, Ctrl-click the part that moves, then insert the joint (Insert Object > Joints). The Inspector sets the other part, the anchor, the axis, limits and the motor.

Members ​

Member
part1The part it is joined to
anchor, axisvec3s in its own part's space
enabledOn or off
limited, lower, upperHinge: degrees; Slider: units
motor, speed, forceDrive it: degrees or units a second, with up to force
angle (Hinge), offset (Slider)How far it has turned / slid (read-only)
length, stiffness, dampingSpring and Rope (length for both)
lua
-- A spinning platform on its post (the platform not anchored: joints move only loose parts)
local spinner = new("Hinge", world.Platform)
spinner.part1 = world.Post
spinner.motor = true
spinner.speed = 45        -- degrees a second
spinner.force = 100000

-- A gate made in KHIM Engine: limited 0 to 90, opened by a button
local gate = world.Gate.Hinge
world.Button.Clickable.clicked:connect(function()
    gate.motor = true
    gate.speed = 60       -- swings to its 90-degree stop and holds there
end)

Joints work on the server. A ClientScript can read them but moves nothing with them.

Movers ​

Put these on a loose part to push it:

MoverDoesMembers
MoverDrives it at a speed, holding it against gravity too: a moving platform, a dronevelocity, strength, relative
SpinnerSpins it: a fan, a rolling wheelspin (radians a second about each axis), strength, relative
ThrusterPushes with a steady force: a rocket, windforce, relative
lua
local drone = new("Mover", world.Drone)
drone.velocity = vec3(0, 0, -10)   -- flies level at 10 units a second

relative = true makes the vector turn with the part (a Thruster's default: a rocket pushes the way it points).

Moving parts with no physics ​

For platforms and doors that should follow an exact path, a Motion (no code) or a tween is simpler than physics:

lua
world.Lift:tween({position = world.Lift.position + vec3(0, 20, 0)}, {time = 4, reverses = true, repeats = -1})

Characters standing on a moving part - tweened, on a joint, spinning - ride along with it.

Raycasts ​

lua
local hit = world:raycast(origin, direction)   -- the first part along the line, or nil
if hit then print(hit.part, hit.position, hit.normal, hit.distance) end

direction's length is how far it looks.