I have a part (Invisible hitbox) that changes material to neon (to light up) when it’s touched and back to smoothplasic when not touched. It’s a bit glitchy since when the player runs around on the part it turns off and on. The main issue is when multiple players are on the same part (Pic 1, 2). I want the part to remain neon until there are no players on the part but when one player leaves the part it switches back. I am guessing it’s an issue with part.touchended but I don’t know of any way to fix the issue. When there’s someone on the part I wish it to stay neon. is it a simple matter or running through all the players on the part or something.
Here is the script.
local hitBox = script.Parent
local startButton = script.Parent.Parent
local buttonValue = startButton:GetAttribute("ButtonValue")
local connections = {}
local function isConnected(player)
return connections[player] ~= nil
end
local function updateNumbersValue()
for player in pairs(connections) do
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local energy = leaderstats:FindFirstChild("Energy")
if energy then
energy.Value = energy.Value + buttonValue -- multiply in the other modifiers
end
end
end
end
hitBox.Touched:Connect(function(otherPart)
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
connections[player] = true
script.Parent.Parent.ButtonLight.Material = Enum.Material.Neon
end
end)
hitBox.TouchEnded:Connect(function(otherPart)
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
connections[player] = nil
script.Parent.Parent.ButtonLight.Material = Enum.Material.SmoothPlastic
end
end)
-- Start touch automation
game:GetService("RunService").Heartbeat:Connect(function()
updateNumbersValue()
end)
So, first of all, if this is on server, runservice.heartbeat is a bit too much for numbers updates, consider updating numbers when a new player enter the zone instead, for player detection I recommend doing this: On touched start a loop that checks how many players are there in the zone through a get partsinpart check having as whitelist all the players characters in the server or a GetPartBoundsInBox, then once there are no more players stop the loop until another player touches the zone again. Do not use touch ended.
Thx for the suggestion. I’ve ended up with this new iteration which seems to increment just fine and the parts material while I’m in the hitbox. While standing still it increments once a second but when I run around on the button it speeds up the incremental a lot. I’m not entirely sure what’s happening since I’m adding the players that have already been calculated into a table so in theory they shouldn’t be added again (is that correct)?
anyway here’s what I have so far.
local players = game:GetService("Players")
local hitBox = script.Parent
local startButton = script.Parent.Parent
local buttonLight = startButton.ButtonLight
local buttonValue = startButton:GetAttribute("ButtonValue")
local timerVariable = 1 -- Timer variable in seconds
local function incrementEnergyForPlayer(player)
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local energy = leaderstats:FindFirstChild("Energy")
if energy then
energy.Value = energy.Value + buttonValue
end
end
end
local function isTouched(otherPart)
if otherPart.Parent then
local char = otherPart.Parent
local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
local player = players:GetPlayerFromCharacter(char)
if player and humanoidRootPart then
incrementEnergyForPlayer(player)
end
end
end
hitBox.Touched:Connect(isTouched)
local lastIterationTime = tick()
local processedPlayers = {}
while true do
local currentTime = tick()
local elapsedTime = currentTime - lastIterationTime
if elapsedTime >= timerVariable then
lastIterationTime = currentTime
processedPlayers = {} -- Reset the processed players for the new iteration
local touchingParts = game.Workspace:GetPartsInPart(script.Parent)
local playersInHitbox = {}
for _, touching in pairs(touchingParts) do
local humanoid = touching.Parent:FindFirstChild("Humanoid")
if humanoid then
local player = players:GetPlayerFromCharacter(touching.Parent)
if player and not processedPlayers[player] then
table.insert(playersInHitbox, player)
processedPlayers[player] = true
end
end
end
if #playersInHitbox > 0 then
buttonLight.Material = Enum.Material.Neon
else
buttonLight.Material = Enum.Material.SmoothPlastic
end
for _, player in ipairs(playersInHitbox) do
incrementEnergyForPlayer(player)
end
end
task.wait() -- Do I need this?
end