How to tell if player gets hit by fast moving object?

I am going to have a ton of unanchored parts being thrown around in my game. How would I tell if parts have a certain velocity to deal damage?

Would I use touched events in every part and measure the speed they’re traveling at? Or is there a better method?

I haven’t really thought this through, but, right off the bat, I think you could have an uncollidable part hitbox that’s locked into the player’s character, is slightly larger than the character (so it detects parts in their moving state before actually colliding with the player’s character), and get the magnitude of the AssemblyLinearVelocity Vector3 of every part that triggers the hitbox’s Touched event (to determine how fast it’s moving, as you requested). Don’t make the hitbox too large, though, make it so if a part touches it, you’re sure it’s hitting the character as well (something a bit more refined to add is that could raycast to extrapolate the moving direction of the part to see if it’s really going to collide with the character or not, especially in case you’re using complex custom characters).

char.humanoidrootpart.touched:Connect(function(hit)
if hit.Velocity > (somespeed).Magnitude then
– do desired outcome here
end
end)

this is quite simple what would be better is maybe a shapecast or you could do this touched event to each part in the character, and then if the speed is above a value then take damage. this could also be done on the server when a character is added to prevent exploitation.

or just what @2112Jay said

No easy answer here, maybe..

Put all the fast-moving parts in their own collision group that doesn’t collide with other parts by default..

And one way using Heartbeat and Region3..

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local trackedParts = {}
local damageThreshold = 50
local damageAmount = 20

function trackPart(part)
    trackedParts[part] = true
end

function untrackPart(part)
    trackedParts[part] = nil
end

workspace.ChildAdded:Connect(function(child)
    if child:IsA("Part") and child.Name == "FlyingPart" then
        trackPart(child)
    end
end)

for _, part in ipairs(workspace:GetDescendants()) do
    if part:IsA("Part") and part.Name == "FlyingPart" then
        trackPart(part)
    end
end

RunService.Heartbeat:Connect(function()
    for part in pairs(trackedParts) do
        if not part.Parent then untrackPart(part)
        elseif part.Velocity.Magnitude >= damageThreshold then
            local region = Region3.new(part.Position - part.Size/2, part.Position + part.Size/2)
            local overlapping = workspace:FindPartsInRegion3(region, part, 10)
            for _, hit in ipairs(overlapping) do
                local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
                if humanoid then humanoid:TakeDamage(damageAmount)
                end
            end
        end
    end
end)

Kind of guessing here… hope you get how this works or can make it work for you.
Trying to do this within one script.

.Touched shall fire the moment the object has collided with the HumanoidRootPart, and thus the velocity you get would be just after the impact. By getting the velocity just a bit before as explained in my post How to tell if player gets hit by fast moving object? - #2 by safeLast120 , you would accurately get the velocity at which it meets with the character.

Also, perhaps the part collides with the right leg instead of the HumanoidRootPart, and it’s not really efficient to connect Touched for each body part, besides of the point made above.

Something similar but I used Touched instead.

local RunService = game:GetService("RunService")
local Model = workspace.Model --model containing parts
local Parts = Model:GetChildren()

local PartVelocities = {}
local Speed = 10 --change this to the desired velocity

local function OnHeartbeat(Time)
	for _, Part in ipairs(Parts) do
		PartVelocities[Part] = Part.AssemblyLinearVelocity.Magnitude
	end
end

RunService.Heartbeat:Connect(OnHeartbeat)

for _, Part in ipairs(Parts) do
	local function OnTouched(OtherPart)
		--check if "OtherPart" belongs to a player's character model
		if PartVelocities[Part] or 0 > Speed then
			--do some code	
		end
	end

	Part.Touched:Connect(OnTouched)
end
1 Like