Hi, I’m pretty new to scripting and I’ve been stuck on this for a while. I’m trying to figure out how to make some kind of impact detection system like in Broken Bones. This is the only thing keeping me from finishing my game, so I’m kind of desperate at this point.
1. What do you want to achieve?
I want to detect when a player hits the ground or another object with force, and be able to measure how big the impact was.
2. What is the issue?
The main problem is reliability and accuracy.
.Touched does register collisions, but it doesn’t really separate small bumps from strong impacts.
Raycasting gave me results sometimes, but they didn’t feel accurate for actual collisions.
Because of this, I can’t get consistent or accurate results with the systems I’ve tried.
3. What solutions have you tried so far?
Using `.Touched’.
Raycasting from the player downward.
Searching Creator Hub and DevForum, but I didn’t find anything that covered this issue properly.
Extra details
What I’d like is a way to reliably measure:
How strong the impact is when a character collides with something.
This approach using workspace:Blockcast() will pretty reliably detect impacts in my testing.
--[[ Variables ]]--
-- Character --
local character = script.Parent
local rootPart = character:WaitForChild("HumanoidRootPart")
--[[ Functions ]]--
local function detectImpact(dt : number) : RaycastResult?
local castParams = RaycastParams.new()
castParams.FilterDescendantsInstances = {character}
castParams.RespectCanCollide = true
local shapeCFrame = rootPart:GetPivot()
local shapeSize = Vector3.new(2, 5, 2)
local castDirection = rootPart.AssemblyLinearVelocity * dt
return workspace:Blockcast(shapeCFrame, shapeSize, castDirection, castParams)
end
local function init() : ()
while true do
local dt = task.wait()
local impactResult = detectImpact(dt)
if impactResult then
print(`Impact at {impactResult.Position} at {rootPart.AssemblyLinearVelocity.Magnitude} studs/s`)
end
end
end
init()
It won’t be 100% up to date since it is independent of the actual physics engine, but because it predicts a collision by a frame duration ahead, it should be pretty reliable.
In Roblox a Humanoid has a RootPart (usually HumanoidRootPart) that you can monitor!
You can (for example):
Continuously track the player’s velocity
Detect when velocity suddenly changes (which indicates an impact)
Measure the magnitude of the change to quantify the force
Heres a really really simple LocalScript (or ServerScript) that calculates impact:
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local root = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local lastVelocity = Vector3.new(0,0,0)
local impactThreshold = 30 -- tweak this to control what counts as a strong hit!
--loop to check velocity every frame
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
local currentVelocity = root.Velocity
local velocityChange = (currentVelocity - lastVelocity).Magnitude
if velocityChange > impactThreshold then
print("Impact detected! Force magnitude:", velocityChange)
-- you can call functions here to deal damage or play effects or whatever you use this for
end
lastVelocity = currentVelocity
end)
how This Works
root.Velocity gives the current speed and direction of the character
(currentVelocity - lastVelocity).Magnitude calculates how much the velocity changed since the last frame
If the change is above your impactThresholdit counts as a strong hit
You can tweak impactThreshold depending on how sensitive you want it!