so ive created a script that will return true if a target gui touched the gui the script is parented too.
local RunService = game:GetService("RunService")
function OnTouch(b)
local a = b.Parent.Parent.Parent.Parent.DragableFrame
local debounce = false
local GuiCollisionService = require(game:GetService("ReplicatedStorage").GuiCollisionService)
GuiCollisionService.isColliding(a, b)
local assets = b:FindFirstChild("assets")
if GuiCollisionService.isColliding(a,b) == true then
b.UIStroke.Enabled = true
repeat wait(0.000001)
until GuiCollisionService.isColliding(a,b) == false
b.UIStroke.Enabled = false
end
end
RunService.Heartbeat:Connect(function()
for i, b in pairs(script.Parent:GetDescendants()) do
if b:IsA("ImageButton") then
coroutine.wrap(OnTouch)(b)
end
end
end)
but when it gets to about over a good 1000 of those imagebuttons, the client starts to lag because of all those scripts in those imagebuttons.
You’re probably thinking: why not just use collectionservice? The problem with that is when all those imagebuttons are put into a table, it still lags because of the time it has to take to iterate over all of them and check if each is touching the target gui
OnTouch requires GuiCollisionService (every time it is called) and determines if it collides.
If they touched, a while-loop is started. (Side note: Anything below 0.015 won’t do any difference, and switch to task.wait() instead of wait())
End loop once they stop touching
This looks, to me, like you are creating a new while loop every hearbeat.
Try switching to events the best you can, it will really ease up some performance issues. Also, move the require outside the function. You don’t need to require it every heartbeat
local RunService = game:GetService("RunService")
local Collectionservice = game:GetService("CollectionService")
local GuiCollisionService = require(game:GetService("ReplicatedStorage").GuiCollisionService)
function OnTouch(b)
local a = b.Parent.Parent.Parent.Parent.DragableFrame
local debounce = false
GuiCollisionService.isColliding(a, b)
if GuiCollisionService.isColliding(a,b) == true then
b.UIStroke.Enabled = true
repeat task.wait()
until GuiCollisionService.isColliding(a,b) == false
b.UIStroke.Enabled = false
end
end
RunService.Heartbeat:Connect(function()
for i, b in pairs(Collectionservice:GetTagged("regions")) do
coroutine.wrap(OnTouch)(b)
end
end)
The main issue you got is the fact that you are doing a lot of checks every heart beat. There is no need to check regions that have not moved. To only check moved regions, use events. Quick example:
local Collectionservice = game:GetService("CollectionService")
local GuiCollisionService = require(game:GetService("ReplicatedStorage").GuiCollisionService)
function OnTouch(a, b)
b.UIStroke.Enabled = GuiCollisionService.isColliding(a,b) -- Will be true if colliding
end
local function hookToOnTouch(obj: GuiBase) -- Makes the gui check for collision whenever it is moved/resized
obj:GetPropertyChangedSignal("Position"):Connect(function()
OnTouch(a, b)
end)
obj:GetPropertyChangedSignal("Size"):Connect(function()
OnTouch(a, b)
end)
end
for _, b in ipairs(Collectionservice:GetTagged("regions")) do -- change to pairs instead of ipairs if this errors
local a = b.Parent.Parent.Parent.Parent.DragableFrame -- a will always be the same for each b (I assume? Otherwise move this back into OnTouch() )
hookToOnTouch(a)
hookToOnTouch(b)
end
a and b are undefined here… but thats ok because i went with a “rendering strategy” where guis would only be tagged if it is inside the player’s screen. this is how it works(in each imagebutton).
local guiInset = game:GetService("GuiService"):GetGuiInset()
local function isInScreen()
local pos = script.Parent.AbsolutePosition + guiInset
return pos.X + script.Parent.AbsoluteSize.X <= (game.Workspace.CurrentCamera.ViewportSize.X * 1.5) and pos.X >= 0
end
script.Parent.Changed:Connect(function(AbsolutePosition)
isInScreen()
if isInScreen() == true then
tagservice:AddTag(script.Parent,"regions")
else
tagservice:RemoveTag(script.Parent,"regions")
end
end)