Roblox physics
Choose deliberately between simulation, character control, hit detection, and visual-only motion;
they are different jobs. Targets Roblox's rolling platform APIs. Pair with physics-tuning for
engine-neutral stability and feel.
When to use
- Use for BasePart assemblies, constraints, collision/query policy, ray/overlap queries, forces,
impulses, moving physical objects, network ownership, or physics cleanup.
- Use when
Touched is unreliable/security-sensitive, parts tunnel or jitter, a mechanism breaks
when anchored, or old BodyMover patterns appear.
When not to use: ordinary Humanoid lifecycle/control belongs to roblox-characters; remote
validation belongs to roblox-networking; decorative UI/world motion may only need a tween.
Decide the system first
| Goal |
Mechanism |
| sustained physical interaction |
unanchored assembly + modern constraints/forces |
| instantaneous physical change |
ApplyImpulse / ApplyAngularImpulse |
| kinematic platform/path |
controlled pivot/transform with an explicit passenger policy |
| character locomotion |
Humanoid/custom character controller (roblox-characters) |
| authoritative hit test |
server raycast/overlap with filters and gameplay validation |
| cosmetic trail/recoil |
local visual motion; no gameplay authority |
Workflow
- Inspect the mechanism. In Studio, visualize assemblies, anchors, constraints, collision
groups, massless parts, and network owners. Identify the assembly root and intended authority.
- Define interaction policy. Write the collision-group matrix and separately decide
CanCollide, CanTouch, and CanQuery. These flags are not interchangeable.
- Choose simulation or query. Do not use
.Touched as a universal hit detector. Use a ray for
a path/line, an overlap query for a volume, and simulation contacts when physical response is
actually required.
- Apply motion at assembly level. Forces on a part affect its assembly. Use modern
LinearVelocity, AngularVelocity, VectorForce, AlignPosition, and AlignOrientation
constraints as appropriate; migrate deprecated BodyMovers when changing that system.
- Set ownership deliberately. Server-own gameplay-critical loose assemblies when required;
client ownership can improve responsiveness but never authorizes gameplay results.
- Bound cost and lifetime. Reuse query parameters, cap query frequency/result count, remove
temporary constraints/attachments, and disconnect event listeners.
- Verify under load and multiplayer. Test anchored/unanchored transitions, mass extremes,
collision matrix, fast motion, multiple clients, ownership changes, streaming, and cleanup.
Pattern: filtered server raycast
local Workspace = game:GetService("Workspace")
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {shooterCharacter}
params.IgnoreWater = true
params.CollisionGroup = "WeaponQuery"
local direction = aimDirection.Unit * MAX_RANGE
local result = Workspace:Raycast(muzzlePosition, direction, params)
if result then
local model = result.Instance:FindFirstAncestorOfClass("Model")
local humanoid = model and model:FindFirstChildOfClass("Humanoid")
if humanoid and serverCanDamage(shooter, model, result.Position) then
humanoid:TakeDamage(serverWeaponDamage(shooter))
end
end
The server must validate the origin/direction against server-known character/weapon state; do not
accept an arbitrary client origin and treat the raycast itself as validation.
Pattern: overlap volume with explicit policy
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {sourceCharacter}
params.CollisionGroup = "DamageQuery"
params.MaxParts = 64
local seen: {[Model]: boolean} = {}
for _, part in Workspace:GetPartBoundsInBox(hitboxCFrame, hitboxSize, params) do
local model = part:FindFirstAncestorOfClass("Model")
if model and not seen[model] then
seen[model] = true
validateAndApplyHit(model)
end
end
Bounds queries use bounding boxes and can include multiple parts from one target; deduplicate and
perform exact/gameplay checks as needed. For exact geometry use WorldRoot:GetPartsInPart(part, overlapParams)
only when its additional cost is justified. Note OverlapParams.RespectCanCollide decides whether a
query honours CanCollide or CanQuery — set it deliberately, or it silently overrides the flag
policy below. OverlapParams.Tolerance controls contact slop.
Assemblies, force, and ownership
- Welded parts form one rigid assembly; force, impulse, velocity, mass, and ownership operate on
that assembly. Anchoring a part changes simulation/ownership and can make an assembly effectively
infinite mass.
- Apply an impulse for a one-time change; use a force or velocity constraint for sustained control.
Setting
AssemblyLinearVelocity is an immediate state change, not a continuous force model.
- Prefer attachments plus modern constraints over
BodyPosition, BodyVelocity, BodyGyro, and
other deprecated BodyMovers when authoring or revising a mechanism.
- Automatic ownership may move nearby unanchored assemblies to clients. Use
SetNetworkOwner(nil) conservatively for critical objects, then measure responsiveness/server
cost. Visualize network owners in Studio.
- A client owner can manipulate physical results and
.Touched observations. The server validates
consequential hits, positions, timing, and permissions independently.
Common failures
| Symptom |
Likely cause |
Remedy |
| welded mechanism will not move |
one part anchored |
inspect full assembly; anchor only intentional world roots |
| force behaves too strongly/weakly |
assembly mass ignored |
inspect AssemblyMass; tune force/impulse by intended acceleration |
| hit misses fast projectile |
discrete touch sampling/tunneling |
swept query — WorldRoot:Blockcast(), Spherecast(), or Shapecast() — plus physics-tuning; do not rely only on .Touched |
| ray hits shooter/effects |
filters/collision group absent |
reuse explicit params and query group |
| same target damaged many times |
overlap returned multiple body parts |
deduplicate by target model and enforce attack ID/cooldown |
| exploit fires impossible touch |
client owns relevant physics |
server query/context validation; deliberate ownership |
| invisible trigger blocks or cannot query |
three flags conflated |
set CanCollide, CanTouch, CanQuery independently |
| mechanism leaks attachments |
temporary constraint lifecycle missing |
own and destroy constraints, attachments, and connections together |
Resources
- Read
references/queries-and-ownership.md for collision/query matrices, assembly debugging,
ownership security, migration choices, and the physics verification matrix.
Related skills
physics-tuning — timestep, jitter, tunneling, mass ratios, and stability methodology.
roblox-characters — Humanoid/custom movement and respawn lifecycle.
roblox-networking — authoritative validation of client-requested physical actions.
roblox-studio-workflow — visualization, Output, and multi-client verification.
Primary references
https://create.roblox.com/docs/physics/assemblies
https://create.roblox.com/docs/physics/network-ownership
https://create.roblox.com/docs/workspace/raycasting
1---
2name: roblox-physics
3description: >
4 Implement Roblox physical simulation and queries with assemblies, anchoring, constraints,
5 collision groups, CanCollide/CanTouch/CanQuery, raycasts and overlap queries, mass, impulses,
6 forces, velocity, moving assemblies, cleanup, and network ownership. Use for Roblox collisions,
7 hit detection, RaycastParams, PhysicsService, projectiles, vehicles, knockback, constraints,
8 deprecated BodyMovers, unstable motion, or client-owned physics exploits.
9---
10
11# Roblox physics
12
13Choose deliberately between simulation, character control, hit detection, and visual-only motion;
14they are different jobs. Targets Roblox's rolling platform APIs. Pair with `physics-tuning` for
15engine-neutral stability and feel.
16
17## When to use
18
19- Use for BasePart assemblies, constraints, collision/query policy, ray/overlap queries, forces,
20 impulses, moving physical objects, network ownership, or physics cleanup.
21- Use when `Touched` is unreliable/security-sensitive, parts tunnel or jitter, a mechanism breaks
22 when anchored, or old BodyMover patterns appear.
23
24**When not to use:** ordinary Humanoid lifecycle/control belongs to `roblox-characters`; remote
25validation belongs to `roblox-networking`; decorative UI/world motion may only need a tween.
26
27## Decide the system first
28
29| Goal | Mechanism |
30|---|---|
31| sustained physical interaction | unanchored assembly + modern constraints/forces |
32| instantaneous physical change | `ApplyImpulse` / `ApplyAngularImpulse` |
33| kinematic platform/path | controlled pivot/transform with an explicit passenger policy |
34| character locomotion | Humanoid/custom character controller (`roblox-characters`) |
35| authoritative hit test | server raycast/overlap with filters and gameplay validation |
36| cosmetic trail/recoil | local visual motion; no gameplay authority |
37
38## Workflow
39
401. **Inspect the mechanism.** In Studio, visualize assemblies, anchors, constraints, collision
41 groups, massless parts, and network owners. Identify the assembly root and intended authority.
422. **Define interaction policy.** Write the collision-group matrix and separately decide
43 `CanCollide`, `CanTouch`, and `CanQuery`. These flags are not interchangeable.
443. **Choose simulation or query.** Do not use `.Touched` as a universal hit detector. Use a ray for
45 a path/line, an overlap query for a volume, and simulation contacts when physical response is
46 actually required.
474. **Apply motion at assembly level.** Forces on a part affect its assembly. Use modern
48 `LinearVelocity`, `AngularVelocity`, `VectorForce`, `AlignPosition`, and `AlignOrientation`
49 constraints as appropriate; migrate deprecated BodyMovers when changing that system.
505. **Set ownership deliberately.** Server-own gameplay-critical loose assemblies when required;
51 client ownership can improve responsiveness but never authorizes gameplay results.
526. **Bound cost and lifetime.** Reuse query parameters, cap query frequency/result count, remove
53 temporary constraints/attachments, and disconnect event listeners.
547. **Verify under load and multiplayer.** Test anchored/unanchored transitions, mass extremes,
55 collision matrix, fast motion, multiple clients, ownership changes, streaming, and cleanup.
56
57## Pattern: filtered server raycast
58
59```lua
60local Workspace = game:GetService("Workspace")
61
62local params = RaycastParams.new()
63params.FilterType = Enum.RaycastFilterType.Exclude
64params.FilterDescendantsInstances = {shooterCharacter}
65params.IgnoreWater = true
66params.CollisionGroup = "WeaponQuery"
67
68local direction = aimDirection.Unit * MAX_RANGE
69local result = Workspace:Raycast(muzzlePosition, direction, params)
70if result then
71 local model = result.Instance:FindFirstAncestorOfClass("Model")
72 local humanoid = model and model:FindFirstChildOfClass("Humanoid")
73 if humanoid and serverCanDamage(shooter, model, result.Position) then
74 humanoid:TakeDamage(serverWeaponDamage(shooter))
75 end
76end
77```
78
79The server must validate the origin/direction against server-known character/weapon state; do not
80accept an arbitrary client origin and treat the raycast itself as validation.
81
82## Pattern: overlap volume with explicit policy
83
84```lua
85local params = OverlapParams.new()
86params.FilterType = Enum.RaycastFilterType.Exclude
87params.FilterDescendantsInstances = {sourceCharacter}
88params.CollisionGroup = "DamageQuery"
89params.MaxParts = 64
90
91local seen: {[Model]: boolean} = {}
92for _, part in Workspace:GetPartBoundsInBox(hitboxCFrame, hitboxSize, params) do
93 local model = part:FindFirstAncestorOfClass("Model")
94 if model and not seen[model] then
95 seen[model] = true
96 validateAndApplyHit(model)
97 end
98end
99```
100
101Bounds queries use bounding boxes and can include multiple parts from one target; deduplicate and
102perform exact/gameplay checks as needed. For exact geometry use `WorldRoot:GetPartsInPart(part, overlapParams)`
103only when its additional cost is justified. Note `OverlapParams.RespectCanCollide` decides whether a
104query honours `CanCollide` or `CanQuery` — set it deliberately, or it silently overrides the flag
105policy below. `OverlapParams.Tolerance` controls contact slop.
106
107## Assemblies, force, and ownership
108
109- Welded parts form one rigid assembly; force, impulse, velocity, mass, and ownership operate on
110 that assembly. Anchoring a part changes simulation/ownership and can make an assembly effectively
111 infinite mass.
112- Apply an impulse for a one-time change; use a force or velocity constraint for sustained control.
113 Setting `AssemblyLinearVelocity` is an immediate state change, not a continuous force model.
114- Prefer attachments plus modern constraints over `BodyPosition`, `BodyVelocity`, `BodyGyro`, and
115 other deprecated BodyMovers when authoring or revising a mechanism.
116- Automatic ownership may move nearby unanchored assemblies to clients. Use
117 `SetNetworkOwner(nil)` conservatively for critical objects, then measure responsiveness/server
118 cost. Visualize network owners in Studio.
119- A client owner can manipulate physical results and `.Touched` observations. The server validates
120 consequential hits, positions, timing, and permissions independently.
121
122## Common failures
123
124| Symptom | Likely cause | Remedy |
125|---|---|---|
126| welded mechanism will not move | one part anchored | inspect full assembly; anchor only intentional world roots |
127| force behaves too strongly/weakly | assembly mass ignored | inspect `AssemblyMass`; tune force/impulse by intended acceleration |
128| hit misses fast projectile | discrete touch sampling/tunneling | swept query — `WorldRoot:Blockcast()`, `Spherecast()`, or `Shapecast()` — plus `physics-tuning`; do not rely only on `.Touched` |
129| ray hits shooter/effects | filters/collision group absent | reuse explicit params and query group |
130| same target damaged many times | overlap returned multiple body parts | deduplicate by target model and enforce attack ID/cooldown |
131| exploit fires impossible touch | client owns relevant physics | server query/context validation; deliberate ownership |
132| invisible trigger blocks or cannot query | three flags conflated | set `CanCollide`, `CanTouch`, `CanQuery` independently |
133| mechanism leaks attachments | temporary constraint lifecycle missing | own and destroy constraints, attachments, and connections together |
134
135## Resources
136
137- Read `references/queries-and-ownership.md` for collision/query matrices, assembly debugging,
138 ownership security, migration choices, and the physics verification matrix.
139
140## Related skills
141
142- `physics-tuning` — timestep, jitter, tunneling, mass ratios, and stability methodology.
143- `roblox-characters` — Humanoid/custom movement and respawn lifecycle.
144- `roblox-networking` — authoritative validation of client-requested physical actions.
145- `roblox-studio-workflow` — visualization, Output, and multi-client verification.
146
147## Primary references
148
149- `https://create.roblox.com/docs/physics/assemblies`
150- `https://create.roblox.com/docs/physics/network-ownership`
151- `https://create.roblox.com/docs/workspace/raycasting`