You can use a .touched event when the part experiences any touching.
for example:
local part = workspace.Part
local damage = 5 —the damage it would take
part.Touched:Connect(function(touched)
local human = touched.Parent:FindFirstChild(“Humanoid”)
if human then
human.Health -= damage
end
end)
script.Parent.Touched:Connect(function(hit)
local hum = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if hum then
hum.Health = hum.Health - whatever health you want to minus
end)
script.Parent.TouchEnded:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
humanoid.Health = humanoid.Health
end
end)
script.Parent.Touched:Connect(function(hit)
local istouching = true
local hum = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if hum then
while istouching == true do
wait()
hum.Health = hum.Health - whatever health you want to minus
if istouching == false then
break
end
end
end)
script.Parent.TouchEnded:Connect(function(hit)
istouching = false
local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
humanoid.Health = humanoid.Health
end
end)
Like how @DataSigh said, use the touched and touched ended like so
local cooldown = .5
local isTouching = false
local part = workspace.Part
local damage = 5 —the damage it would take
part.Touched:Connect(function(touched)
local human = touched.Parent:FindFirstChild(“Humanoid”)
isTouching = true
while isTouching do
if human then
human.Health -= damage
wait(cooldown)
end
end
end)
part.TouchEnded:Connect(function(touched)
if touched.Parent:FindFirstChild(“Humanoid”) then
isTouched = false
end
end)
local DAMAGE = 10
local INTERVAL = 1/30
local touchingHumanoids = {}
coroutine.wrap(function()
while true do
for humanoid in pairs(touchingHumanoids) do
humanoid:TakeDamage(DAMAGE)
end
wait(INTERVAL)
end
end)()
script.Parent.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = true
end
end)
script.Parent.TouchEnded:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = nil
end
end)
It might be cleaner to just connect to RunService.Heartbeat on that coroutine, I don’t know
script.Parent.Touched:Connect(function(hit)
local istouching = true
local hum = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if hum then
while istouching == true do
wait()
hum.Health = hum.Health - whatever health you want to minus
if istouching == false then
break
end
end
end)
script.Parent.TouchEnded:Connect(function(hit)
istouching = false
local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
humanoid.Health = humanoid.Health
end
end)
You can try moving the coroutine part to the end and throwing the coroutine wrapper away?
local DAMAGE = 10
local INTERVAL = 1/30
local touchingHumanoids = {}
script.Parent.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = true
end
end)
script.Parent.TouchEnded:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = nil
end
end)
while true do
for humanoid in pairs(touchingHumanoids) do
humanoid:TakeDamage(DAMAGE)
end
task.wait(INTERVAL)
end
You’re technically creating a new thread for .Touched and .TouchEnded events every time it fires anyway.
I just realized this would cause problems if you e.g. poked a leg outside of the damage part, that would make the humanoid stop getting damaged even if part of the character is still inside.
Old Solution
I would either just ditch the events altogether and use :GetTouchingParts
local DAMAGE = 10
local INTERVAL = 1/30
local touchingHumanoids = {}
script.Parent.Touched:Connect(function() end)
while true do
for _, part in ipairs(script.Parent:GetTouchingParts()) do
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = true
end
end
for humanoid in pairs(touchingHumanoids) do
humanoid:TakeDamage(DAMAGE)
end
table.clear(touchingHumanoids)
task.wait(INTERVAL)
end
or I would try to keep a set of all parts touching this part, extract every humanoid from all the parts and damage them.
local DAMAGE = 10
local lNTERVAL = 1/30
local touchingParts = {}
local touchingHumanoids = {}
script.Parent.Touched:Connect(function(hit)
touchingParts[hit] = true
end
script.Parent.TouchEnded:Connect(function(hit)
touchingParts[hit] = nil
end
while true do
for part in pairs(touchingParts) do
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid then
touchingHumanoids[humanoid] = true
end
end
for humanoid in pairs(touchingHumanoids) do
humanoid:TakeDamage(DAMAGE)
end
table.clear(touchingHumanoids)
task.wait(INTERVAL)
end
This would lead to the same pattern but more complicated, so I would just use :GetTouchingParts.
I would use a counter and increment/decrement it whenever the kill brick is touched/no longer touched by a part respectively.
local DAMAGE = 10
local INTERVAL = 1/30
local touchingHumanoids = {}
script.Parent.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if not humanoid or humanoid.RootPart == hit then return end
if touchingHumanoids[humanoid] then
touchingHumanoids[humanoid] += 1
else
touchingHumanoids[humanoid] = 1
end
end)
script.Parent.TouchEnded:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if not humanoid or humanoid.RootPart == hit then return end
if touchingHumanoids[humanoid] then
touchingHumanoids[humanoid] -= 1
if touchingHumanoids[humanoid] == 0 then
touchingHumanoids[humanoid] = nil
end
end
end)
while true do
for humanoid in pairs(touchingHumanoids) do
-- if the humanoid is destroyed, remove it from the loop
if not humanoid:IsDescendantOf(game) then
touchingHumanoids[humanoid] = nil
continue
end
humanoid:TakeDamage(DAMAGE)
end
task.wait(INTERVAL)
end
I added the check humanoid.RootPart == hit because the HRP can somehow register a Touched event but never unregister it after the fact. I have no idea why that happens. The torso fills that area anyway, so there should be virtually no discrepancies.