Hello.
In this game, I have a part that kills players (whoop, didn’t see that one coming)
But an issue I encountered is that since it only damages players while it’s transparency = 0, it will not damage the player if it’s already inside the part when the transparency becomes 0.
(The part checking transparency is within the dmg function)
repeat task.wait() until not script.Parent:IsA("Script")
local sound = game:GetService("SoundService").udmg
local myname = script.Parent.Name
local function dmg(character)
if not character:FindFirstChildOfClass("NumberValue") then
if character:FindFirstChild("Defending") then
if myname == "checker" or
myname == "horizontal" or
myname == "horizontal2" or
myname == "vertical" or
myname == "vertical2" then
character.Humanoid:TakeDamage(25)
elseif myname == "bullet" or myname == "spin" then
character.Humanoid:TakeDamage(15)
end
else
if myname == "checker" then
character.Humanoid:TakeDamage(40)
elseif myname == "bullet" or myname == "spin" then
character.Humanoid:TakeDamage(25)
end
end
local highlight = character.Highlight
if highlight.FillColor ~= Color3.new(1, 0, 0) then
highlight.FillColor = Color3.new(1, 0, 0)
end
highlight.FillTransparency = 0.5
game:GetService("TweenService"):Create(highlight, TweenInfo.new(
0.2,
Enum.EasingStyle.Linear,
Enum.EasingDirection.Out,
0,
false,
0), {FillTransparency = 1}):Play()
sound:Play()
local field = Instance.new("NumberValue")
field.Parent = character
game:GetService("Debris"):AddItem(field, 1)
end
end
script.Parent.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") and script.Parent.Transparency == 0 then
dmg(hit.Parent)
end
end)
-- Yoinked from gamemaster4268 on devforums
local RunService = game:GetService("RunService")
local part = script.Parent
if script.Parent.Transparency == 0 then
RunService.Heartbeat:Connect(function()
local parts = part:GetTouchingParts()
for i,v in ipairs(parts) do
local character = v:FindFirstAncestorOfClass("Model")
if character then
local player = game.Players:GetPlayerFromCharacter(character)
if player then
dmg(character)
end
end
end
end)
One issue, when I remove the script.Parent.Touched:Connect(function(hit), the part below it, RunService.Heartbeat:Connect(function(), does nothing, and the part is harmless. When I remove RunService.Heartbeat:Connect(function() though, the original issue of the part not damaging a player that’s already touching it when it activates returns.
this stops the heartbeat connection if the part is not transparent:
if script.Parent.Transparency == 0 then
RunService.Heartbeat:Connect(function()
GetTouchingParts() is tied to touch physics.
If there’s no Touched/TouchEnded listener (no TouchInterest), Roblox often doesn’t maintain the touching set, so GetTouchingParts() returns nothing. That’s why removing the Touched connection made the part “harmless.”
cleaned it up a little tell me if it works:
-- ServerScript inside the damaging Part
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Debris = game:GetService("Debris")
local part = script.Parent
-- Ensure queries work
part.CanQuery = true
-- === CONFIG ===
local myname = part.Name -- "checker", "horizontal", "bullet", "spin", etc.
-- Utility: get character from any descendant
local function getCharacter(inst: Instance)
local m = inst and inst:FindFirstAncestorOfClass("Model")
if m and m:FindFirstChild("Humanoid") then return m end
end
-- Your damage function (lightly guarded)
local function dmg(character: Model)
if not character or not character:FindFirstChild("Humanoid") then return end
if character:FindFirstChildOfClass("NumberValue") then return end -- 1s cooldown marker
local hum = character.Humanoid
local defending = character:FindFirstChild("Defending") ~= nil
if defending then
if myname == "checker" or myname == "horizontal" or myname == "horizontal2"
or myname == "vertical" or myname == "vertical2" then
hum:TakeDamage(25)
elseif myname == "bullet" or myname == "spin" then
hum:TakeDamage(15)
end
else
if myname == "checker" then
hum:TakeDamage(40)
elseif myname == "bullet" or myname == "spin" then
hum:TakeDamage(25)
end
end
-- highlight feedback (only if exists)
local highlight = character:FindFirstChild("Highlight")
if highlight then
if highlight.FillColor ~= Color3.new(1,0,0) then
highlight.FillColor = Color3.new(1,0,0)
end
highlight.FillTransparency = 0.5
TweenService:Create(highlight, TweenInfo.new(0.2, Enum.EasingStyle.Linear), {FillTransparency = 1}):Play()
end
-- sound (only if exists)
local ssvc = game:GetService("SoundService")
local sound = ssvc:FindFirstChild("udmg")
if sound then sound:Play() end
-- 1s per-character cooldown
local field = Instance.new("NumberValue")
field.Name = "DamageCooldown"
field.Parent = character
Debris:AddItem(field, 1)
end
-- Overlap query params (exclude the hazard itself)
local overlap = OverlapParams.new()
overlap.FilterType = Enum.RaycastFilterType.Exclude
overlap.FilterDescendantsInstances = {part}
local function hazardActive()
-- Drive this however you like; you used Transparency as the on/off gate
return part.Transparency == 0
end
-- Optional: keep Touched for instant reactions (not required for overlap to work)
part.Touched:Connect(function(hit)
if not hazardActive() then return end
local character = getCharacter(hit)
if character then dmg(character) end
end)
-- Poll overlaps every frame while active (catches players already inside)
RunService.Heartbeat:Connect(function()
if not hazardActive() then return end
local touching = workspace:GetPartsInPart(part, overlap)
for _, p in ipairs(touching) do
local character = getCharacter(p)
if character then
dmg(character)
end
end
end)
That explains it, thanks!
Your code works as well.
One question, what does this colon do? local function dmg(character: Model)
Does it just give more context, so you know you need to input a model?
The : is used for type checking, so you know when you are programming it has that box where if you press enter it auto completes? Well when you get the parameter though the function the variable type will always be nil even though the instance does exist. So that colon will make the system know oh that is a model or folder, which in result will give that variable the custom functions that it might have.
TD:LR it makes it so the system what type the variable it is looking at and making it easier to program, it is not needed but a very useful habit that will making scripting 10x faster.