Appearance
Sockets
The eighteen places on a body where an object can hang. Used by self:hold, by world:spawn{ hold = }, and by worn items.
The names
| Socket | |
|---|---|
head | face |
eyes | mouth |
left_ear | right_ear |
neck | chest |
back | waist |
left_shoulder | right_shoulder |
left_hand | right_hand |
left_wrist | right_wrist |
left_foot | right_foot |
right_hand is the default anywhere a socket is optional.
A name that is not on this list is refused with "socket".
The axes are the same on every socket
This is the part worth memorising:
| Axis | Direction |
|---|---|
+x | right |
+y | up |
−z | forward |
Relative to the body — and the hand, the back and the first-person eye all agree. So pos = { x = 0, y = 0, z = 0.14 } is fourteen centimetres behind the socket, whichever socket it is, and a number you found for one is a real starting point for another.
rot is in degrees, like every other angle in this API.
scale multiplies the size the object already has in the world. They are two different numbers, not one: either leave this at 1 and size the object in the editor, or leave the object at 1 and size it here.
Why the axes agree. The engine divides out the skeleton's own rest orientation, which belongs to whoever rigged the avatar and has nothing to do with your object. What survives that is the animation — so a weapon in a hand still swings with the arm.
Every socket needs its own pose
A rifle lies across a back differently from how it sits in a fist. There is no default the engine could invent, because where a thing rests depends on the thing.
Left unstated, an object is centred on the bone with no rotation — which for anything longer than a coin means it runs through the body.
luau
local GRIP = {
hand = { pos = { x = 0.06, y = -0.02, z = -0.14 },
rot = { x = 0, y = 90, z = 0 } },
back = { pos = { x = 0, y = 0.10, z = 0.14 },
rot = { x = 0, y = 90, z = 30 } },
}
self:hold({ player = id, at = "right_hand", pos = GRIP.hand.pos, rot = GRIP.hand.rot })Read the back pose above as: fourteen centimetres backwards, ten centimetres above the socket, the same turn as the hand, and thirty degrees of roll to lay it on a diagonal.
Finding the numbers
Do not guess them and do not compute them. Open the grip window — </> → Pegada — which lists everything you are carrying, one row per socket, and hands back a table you paste straight into the call. Adjust while the object is in your hand and you can see it.
Moving between sockets
Calling hold again with a different at moves the object. There is no second verb, and the object stays in the same person's possession — the engine treats the second call as a move, not as a fresh pickup, so no new interaction is required.
luau
-- onto the back
self:hold({ player = id, at = "back", pos = GRIP.back.pos, rot = GRIP.back.rot })
-- and out again
self:hold({ player = id, at = "right_hand", pos = GRIP.hand.pos, rot = GRIP.hand.rot })Add smooth = 0.2 and it slides instead of snapping.
In first person, a slide between the back and the hand is ignored, and it has to be. The back is a bone behind your head and the hand is the camera itself, so interpolating between them passes the object through your own eye. Others still see the real movement in third person.
