Skip to main content

Physics

The Physics table queries the game's physics world. Its raycast finds the first thing with collision along a line: the ground, buildings, props, vehicles, characters. Use it for line of sight checks, to find where a shot or a look ray lands, to snap things to surfaces, or to find which synced object the player is looking at.

Available on: Client

The query runs on this client's copy of the world, so it only sees what is streamed in around this player.

Functions​

Physics.Raycast(from, to, layer)​

Casts a ray from from to to and returns the first hit. layer selects which kinds of collision the ray hits: PfxLayer.RaycastDefault is the usual choice; PfxLayer.RaycastEverythingPhysical is meant to hit every physical body.

The ray can hit the local player's own character. Start it a little away from the player (or beside them) when you cast from the player's position.

Parameters

NameTypeDescription
fromvec3Start of the ray, in world coordinates.
tovec3End of the ray, in world coordinates.
layerPfxLayerThe collision layer of the ray, which decides what it collides with.

Returns a new table:

FieldTypeDescription
hasHitbooleantrue when the ray hit something between from and to. The other fields are only present when it is true.
hitPosvec3The point that was hit.
normalvec3The surface normal at the hit point (a unit vector pointing out of the surface).
hitDistancenumberThe distance in meters from from to the hit point.
gameObjectGameObject or nilThe game object that was hit, nil when what was hit has no game object (terrain, for example). Its GetPosition, GetRotation and GetEulerRotation give the object's transform.
netObjecthandle or nilThe synced object that was hit, as its typed handle (PlayerObjectHandle, VehicleHandle, MountedGunHandle, RigidObjectHandle, NPCHandle, TetherHandle or SandstormHandle). nil when the hit is not a synced object.

Example

-- what is the player looking at? (camera ray, 300 m)
Cmd.Add("look", function()
local from = Camera.GetPosition()
local aim = World.LocalPlayer():AsPlayer():GetAimPosition()
local to = from + (aim - from):normalize() * 300

local hit = Physics.Raycast(from, to, PfxLayer.RaycastDefault)

if not hit.hasHit then
print("nothing within 300 m")
return
end

print(string.format("hit at %.1f m, normal %s", hit.hitDistance, tostring(hit.normal)))

if hit.netObject then
print("that is a synced object, net id " .. hit.netObject:GetNetId())
end
end)
-- snap a position to the ground below it
local function ground_below(position)
local hit = Physics.Raycast(position + vec3(0, 50, 0), position - vec3(0, 200, 0), PfxLayer.RaycastDefault)

return hit.hasHit and hit.hitPos or nil
end