Use Cases
Due to the library being completely decoupled from physical parts, you can run collision logic directly on object data, which is helpful for all kinds of applications where you don’t want a physical part to exist just to run a collision query. One example for this would be lag compensation where you would otherwise have to rewind all the physical player hitboxes just to use the native roblox methods.
Additionally, raycasts and shapecasts in this library still report hits when the cast started inside of the shape its checking against, which is desirable for hit detection in general.
This also covers capsules, as capsules are very useful for collision detection in general.
Features
- Broad Phase
- Dynamic AABB Trees for efficient candidate selection
- Narrow Phase
- special-cased functions for common primitives
- GJK for all other primitives
- raycast and shapecast for all primitives
- MPR for collision information
Installation
Either get the .rbxm from the latest release or through wally:
bolt = "unityjaeger/bolt@0.3.3"
Performance
For Intersection tests you can expect the same performance as equivalent roblox methods, in some cases Bolt will be even faster.
![]()
Here is an example of GetPartsInPart vs. Bolt’s Broad Phase + GJK implementation, as you can see Bolt beats PartsInPart by roughly 15%, it would be even faster if special-cased intersection methods were used.
Known Limitations
GJK casts will not have usable contact information for cases where the cast starts inside of the other shape, and normals will not always be what you expect around vertices/edges due to the way GJK performs shapecasts. If you need penetration depth + a normal in this case, use MPR.
Quick Example
-- setup
local tree = bolt.aabb_tree.new({ aabb_padding = 1 })
-- register objects (once, or when they are created)
for id, obj in objects do
tree:insert(id, obj.cf, obj.shape)
end
-- every frame, update moved objects
for id, obj in objects do
tree:move(id, obj.cf)
end
-- broad + narrow phase query
local candidates = tree:query_shape(query_cf, query_shape)
for _, id in candidates do
local obj = objects[id]
--use the appropriate collision function, or gjk for the narrow phase check
if bolt.collision.box_box(query_cf, query_shape, obj.cf, obj.shape) then
-- confirmed hit
end
end

