So for some reason the touched event when connected to my character’s parts just keep firing like if it’s in a loop. It seems to be only a certain place since if I try it on a default baseplate it works normally. A simple script like this one:
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
print(tostring(part))
end)
end
--(i wrote this on my phone)
Would constantly fire the parts name over and over again, yet the same script would work fine on a default place. It doesn’t seem to relate to animations or parts inside of the character (ragdoll collision parts) either.
local debounce = false
if not debounce then
debounce = true
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
print(tostring(part))
end)
end
task.wait(1)
debounce = false
end
local debounce = false
game.Players.PlayerAdded:Connect(function(Player)
local Character = Player.CharacterAdded:Wait() or Player.Character
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
if debounce == false then
debounce = true
print(tostring(part))
task.wait(1)
debounce = false
end
end)
end
end)
So I tried your code, it seems to only merely slow down the touched signal which isn’t really optimal if someone is going fast thru a part that (for example, ragdolls them).
Normally touched would fire everytime you just touch a part and not fire again until you move or something. For me, it fires everytime I’m touching a part.
Again it seems to be only this specific place that has this issue.
I’m not sure if something is changing my position ever-so-slightly that it constantly fires the touched or not.
Im looking at this and yeah, its a loop going towards your character , since the children are in your character and they are touching each other, plus your Humanoid, and workspace items, it will repeat
There is also an error here unless i’m missing something:
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
print(tostring(part))
end)
end -- Error
Thats Because it IS in a loop, what you are using is called a For Loop. you Usually use Touched in a for loop when you want it to fire on multiple parts.
For Example this ServerScriptService script:
function Touched()
print("touched")
end
for _,Parts in pairs(workspace:GetChildren()) do
if Parts:IsA("Part") then
Parts.Touched:Connect(Touched)
end
end
You’re wrong. It’s not supposed to repeatedly fire what part I’m touching. It’s only support to fire when I just touch a part.
Here’s some gifs to showcase.
They’re all using the code below in StarterCharacterScripts
local Character = script.Parent
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
print(tostring(part))
end)
end
Default Baseplate running the code: (it prints everytime I move)
Specific game running the exact same code (it prints repeatedly, stops printing if i jump since im not touching anything.
Thats Exactly what i mean, your bodyparts are touching something or themselves
My Script:
function Touched()
print("touched")
end
for _,Parts in pairs(workspace:GetChildren()) do
if Parts:IsA("Part") then
Parts.Touched:Connect(Touched)
end
end
This script is a global script, anything you touch that is a part, will print touched
Your Script:
local Character = script.Parent
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
print(tostring(part))
end)
end
This script is looping through the Players character and is being told to fire when it touches something, and everytime it touches something, i will print what it is.
if youre trying to get the name of the object youre touching:
for _,Parts in pairs(workspace:GetChildren()) do
function Touched(hit)
print(Parts)
end
if Parts:IsA("Part") then
Parts.Touched:Connect(Touched)
end
end
this shouldn’t spam the Output unless you are running around.
Yes it does, everytime the game detects you are moving on the Part, or on the part itself. It fires .Touched. if you are printing, It will spam the function unless you add a delay or stop moving.
Empty place with script in ServerScriptService
It still only detects when I move around, and only when I hit parts I had not previously hit
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
wait(5)
print("ready")
for i, v in pairs(character:GetChildren()) do
if v:IsA("BasePart") then
v.Touched:Connect(function(part)
print(tostring(part))
end)
end
end
end)
end)
The “STREET” part is a normal part. Just in case something is wrong with it, I copied the default baseplate and put it outside of the normal map and then used commands to fly there. It does the same.
2. Yes.
3. There are custom animations, but even if I put it on a default place, it still works normally and doesn’t spam it. There’s another script that flucates your walkspeed and jumppower (client-sided), but again, it works fine on the empty place.
Right now I’m looking through scripts to see if it’s actively modifying anything regarding my character.
Most modifications like smooth movement don’t seem to relate to this touch connection spam.
Okay, just as an update, a serverscript around 3.5k lines that handles pretty much 90% of the game seems to be at fault of this touch spam. Looking into it.
Most touched scripts are in the object being touched and check to see what touches the item, then checks if that item is a child of a Humanoid. If it is it gets the player from that contact and performs the section of script you want on that item or that player.
It then uses a debounce to keep it from firing again. The article posted has a good description of this phenomenon.
touched fires multiple times every time an item contacts another one. This is really problematic when using a player because they are almost always moving.
local LastTouch = 0 --store the game tick of the last touch
local Cooldown = 0 --change cooldown
for i, v in pairs(Character:GetChildren()) do
v.Touched:Connect(function(part)
local Now = tick()--this moment in time
if Now >= LastTouch+Cooldown then
LastTouch = Now--update the last touch tick
else
return--cancel, need to wait more time
end
if part:IsDescendantOf(Character) then
return --cancel, it's a part inside our own character
end
print(tostring(part))
end)
end
you just need to think of it in terms of where to cancel the function (return nil) and store a timestamp and a cooldown value and it becomes trivial
I was suggesting that the script be taken out of the player and put into the Part you want to register the touch.
Makes it much easier to check if the item (in this case a player) touching the Part has a Humanoid inside it.
I don’t recall anyone (I’m not much of a scripter, but I have read a lot of posts about checking for touched) checking inside the player to see if the player has touched a certain Part. Seems like even if the script senses a touch from inside the player and the function has to check if it’s a player Part or the Part you want to check for then it’d start causing lag running every time, even with your debounce.
Also, if it’s a player script wouldn’t that be local, and able to be hacked?
As I understand it if it was a server script inside the Part in the workspace Clients wouldn’t be able to change the touched function.
It really depends on the purpose of the script. I imagine they have some reason for designing it this way. I personally wouldn’t, or if I did do something similar I would only check collisions on the PrimaryPart (to detect if you’re inside a part with no collisions for example without having a script in every part)
I think my reply should work for OP just fine. I’m just trying to help him with his problem rather than tell him he should be designing his system different lol
Also, if it’s a player script wouldn’t that be local, and able to be hacked?
Should probably mention to you the client is in charge of server touched connections involving parts owned by the network. (e.x you can turn off CanTouch on a kill brick client-side and the server-side kill-brick won’t hurt you because your client never sends the touch signal packets for the server to execute its code)
the reason it works this way is because collision detection is less expensive when it’s off-loaded to the client