I’m trying to make a smooth pressure plate door for games like 2 Player Puzzle Obbies. It works, but the effects play repeatedly despite me even putting an effect debounce.
local Button = script.Parent.Button
local Hitbox = script.Parent.Hitbox
local Part = script.Parent.Parent.Part
Solidize = script.Parent.Configuration.Solidize.Value
SomeonesOn = false
EffectDB = false
local Green = BrickColor.new("Shamrock")
local Black = BrickColor.new("Black")
local Particles = Button.Particles
local Sound = Button.Sound
if Solidize == true then
Part.Transparency = .5
Part.CanCollide = false
else
Part.Transparency = 0
Part.CanCollide = true
end
local function GetTouchingParts()
local connection = Hitbox.Touched:Connect(function() end)
local results = Hitbox:GetTouchingParts()
connection:Disconnect()
return results
end
while true do
task.wait()
local touchingParts = GetTouchingParts()
for i, v in pairs(touchingParts) do
if v.Parent:FindFirstChild("Humanoid") then
if not EffectDB then
EffectDB = true
Particles:Emit(10)
Sound:Play()
end
Button.BrickColor = Black
if Solidize then
Part.Transparency = 0
Part.CanCollide = true
else
Part.Transparency = .5
Part.CanCollide = false
end
else
if EffectDB then
EffectDB = false
end
Button.BrickColor = Green
if Solidize then
Part.Transparency = .5
Part.CanCollide = false
else
Part.Transparency = 0
Part.CanCollide = true
end
end
end
end
Aight so, basically this whole snippet here is screwed up.
for i, v in pairs(touchingParts) do
if v.Parent:FindFirstChild("Humanoid") then
if not EffectDB then
EffectDB = true
Particles:Emit(10)
Sound:Play()
end
Button.BrickColor = Black
if Solidize then
Part.Transparency = 0
Part.CanCollide = true
else
Part.Transparency = .5
Part.CanCollide = false
end
else
if EffectDB then
EffectDB = false
end
Button.BrickColor = Green
if Solidize then
Part.Transparency = .5
Part.CanCollide = false
else
Part.Transparency = 0
Part.CanCollide = true
end
end
end
When you use GetTouchingParts, you have to be aware that a player instance has many many many parts, which dont all have Humanoid as a child, and several of which that do. That means you’re effectively setting and resetting your EffectDB multiple times for every single player on the part with each iteration of the loop. Thus particles and sounds will be spammed.
What you want to do instead is something like this. Have two variables, one to act as a flag to see if there was a human standing on the part this iteration(You already have a variable that could be used for this called someonesOn), and another to check whether to emit effects(your effectdb). You want to set someonesOn to false before the for loop, and set it to true inside the for loop if a humanoid is found. At the end of the script, after the foor loop, you can then reset effectDB if someonesOn is false.
For a debounce to work with Touched events and a Humanoid it needs a task.wait(some time that alows the touched event to fire, but not fire again each and every time a player’s part touches the Hitbox.
The while true dotask.wait() will allow your GetTouchingParts function to fire every .03 seconds.
Put a print("player touched") statement right after your Touched event. That will show you exactly how many times the player (or their touching Parts) are touching the Hitbox.
This makes a lot more sense, but I still don’t fully understand. I switched my script a little bit but it’s still spamming the particles because of how accessories’ handles aren’t direct children of the character model. Could you walk me through it a little bit more? Sorry for needing this much help.
local Button = script.Parent.Button
local Hitbox = script.Parent.Hitbox
local Part = script.Parent.Parent.Part
Solidize = script.Parent.Configuration.Solidize.Value
SomeonesOn = false
EffectDB = false
local Green = BrickColor.new("Shamrock")
local Black = BrickColor.new("Black")
local Particles = Button.Particles
local Sound = Button.Sound
if Solidize == true then
Part.Transparency = .5
Part.CanCollide = false
else
Part.Transparency = 0
Part.CanCollide = true
end
local function GetTouchingParts()
local connection = Hitbox.Touched:Connect(function() end)
local results = Hitbox:GetTouchingParts()
connection:Disconnect()
return results
end
while true do
task.wait()
local touchingParts = GetTouchingParts()
for i, v in pairs(touchingParts) do
if v.Parent:FindFirstChild("Humanoid") then
SomeonesOn = true
Button.BrickColor = Black
if Solidize then
Part.Transparency = 0
Part.CanCollide = true
else
Part.Transparency = .5
Part.CanCollide = false
end
else
Button.BrickColor = Green
if Solidize then
Part.Transparency = .5
Part.CanCollide = false
else
Part.Transparency = 0
Part.CanCollide = true
end
end
end
if SomeonesOn then
EffectDB = true
Particles:Emit(10)
Sound:Play()
else
EffectDB = false
end
end
Ehh, the way you do it there, the EffectDB value ends up serving no purpose. You want a value that resets in the start of the while loop, or anytime before the for loop, someonesOn is never reset. And then you want a variable you can use to tell whether the effect has been played yet or not. This value should only reset when theres nobody on the part.
Essentially something like this
local hasEffectEmitted = false
local isHumanoidOn = false
while true do
isHumanoidOn = false
local touchingParts = GetTouchingParts()
for i, v in pairs(touchingParts) do
if v.Parent:FindFirstChild("Humanoid") then
isHumanoidOn = true
break
end
end
if not hasEffectEmitted and isHumanoidOn then
hasEffectEmitted = true
Particles:Emit(100)
Button.BrickColor = BrickColor.random()
elseif not isHumanoidOn then
hasEffectEmitted = false
Button.BrickColor = BrickColor.Black()
end
task.wait()
end