Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Is there a way to more precisely control touched:connect?

Asked by 5 years ago

So im essentially hitting two issues here, neither of which I have been able to resolve, or narrow a source down for.

The first of which is that I have a script to detect a player collision with a child part from a cloned workspace model. The part fires on collision, but it fires several thousand times per second. Ive managed to slow it down to about 100 times per second, but even after a gentle key tap, it still triggers and calls my function upto 15~ times, even with a variable delay (that doesnt seem to be working?)

I just want to be able to collide with the part until the function is triggered, at which case a second function (below) triggers and freezes the players movements (thus denying anymore collision detections), but this doesnt seem to be working as intended and im not sure why.

local repStorage = game:GetService("ReplicatedStorage")
local triggered = repStorage:WaitForChild("TestTrigger")
local lock = true

local function test(body)
    if (body.Parent:FindFirstChild("Humanoid")) then
        local Player = game.Players:GetPlayerFromCharacter(body.Parent)
        local x = math.random(200)
        if x > 195 then
            triggered:FireClient(Player)
        end
    end
end

while #_G.loadedRegions > 0 do
    wait()
    for i = 1, #_G.loadedRegions do
        for name, child in pairs(game.Workspace[_G.loadedRegions[i]]:GetChildren()) do
            if child.Name == "Loot" and lock == true then
                lock = false
                child.Touched:connect(test)
                wait(1)
                lock = true
            end
        end
    end
end

My Second issue is that, while the above function atleast operates the way its supposed to, to a degree. After the first time the player is frozen on a successful run of the math.rand func, the player is continually frozen and unfrozen rapidly by the script, even when not meeting the threshold requirements of the x variable. Once again im not sure whats going down here. Any insights are appreciated

local MasterControl = require(game.Players.LocalPlayer:WaitForChild("PlayerScripts"):WaitForChild("ControlScript"):WaitForChild("MasterControl"))
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
local triggered = ReplicatedStorage:WaitForChild("TestTrigger")


local function holding()
    MasterControl:Disable()
    --GUIFunctions
    wait(0.5)
    MasterControl:Enable()
end

battleTriggered.OnClientEvent:Connect(holding)

1 answer

Log in to vote
1
Answered by 5 years ago

Hopefully when I am through, your script will be up and running properly. The first problem you have is the debounce (you call it lock). You are only checking it before the event is triggered and not when the event is triggered. Even if you did, because of the way your structure is, you would have an issue if the player touched multiple different children at the same time. You have the variable defined in a way that once the script changes it, every time anything gets hit, it will wait 1 second and then change the value, which is will not work properly. My way to fix this would be to have a function you call that can localize the variable, thus leading to no mix up errors. For this example I will use the code from the wiki as an example:

local function lock(func)
    local isRunning = false    -- Create a local debounce variable
    return function(...)       -- Return a new function
        if not isRunning then
            isRunning = true

            func(...)          -- Call it with the original arguments

            isRunning = false
        end
    end
end
-- then we attach your event to this:
child.Touched:Connect(lock(test)) -- use uppercase C for connect

Because I have not used the above code before and am unsure about some things I will tell you how I manage it. I have a module script that returns a function and while I am looping through all the items that need touched I put them as arguments to the function my module script returns. The function in the module script contains the Touched event and a debounce. Using that method has always worked for me, but you can decide which path you want to take. Another issue is that you are using a while loop which runs VERY often. I do not recommend that. Read this article for more info. Because you are using the while loop, you may be creating new touched events for the same object. This means that even with a good debounce system your game will continue to have multiple instances of touching. One way to avoid this would be to have an array that contains the objects that you have already created events for (It would require something unique in each object). For instance each child might have a special Id:

local foundIds = {}
local function checkForMatch(list, Id)
    for i,v in pairs(list) do
        if v == Id then
            return false -- if we have already found it no need to continue
        end
    end
    return true -- if nothing has been found we return true
end
for i,v in pairs(whateverParent:GetChildren()) do
    if v:FindFirstChild("Id") then
        if checkForMatch(foundIds, v.Id.Value) then
            table.insert(foundIds, v.Id.Value)
            -- touched event/function here whatever you will do in the future
        end
    end
end -- if they all have unique names then you could just do it by name and not Id   

Another thing to note: while condition do loops should be avoided if there is already an event for what it is trying to accomplish. For instance, instead of looping every few seconds to check and see if the value of a BoolValue changed, I can just use the Changed event for that BoolValue. The same goes for children of objects. There is an event called ChildAdded which fires when a child has been added. So, instead of you looping to catch new children, why don't you use the ChildAdded event. I will note that this may not work in your circumstance. It is just a recommendation from me to you. Finally, the _G. _G usage is not recommended nor encouraged on the Roblox platform because we have things like, IntValues, BoolValues, Other values, The workspace (and other services like ServerStorage), and ModuleScripts. Try to avoid using _G and in your circumstance --I may be wrong-- it seems unnecessary when better, more conventional methods are available. I hope this all helps and have a great day scripting! Note: any additional comments/questions can be asked in the comment section below. gl

Ad

Answer this question