So, my work is pretty simple: making a selection system with highlights. I got it to work well, but I’ve noticed that the disappearing tween (when you unfocus your mouse off of an interactable object) is INCREDIBLY SLOW, even though I’ve specified 0.2 as the duration in the TweenInfo.
I’m genuinely unsure why is this happening. Sure, setting the time to be a really low number might solve it, but it’d be nice if I could use a single number for the tweens rather than two separate ones.
LocalScript (location: game → StarterPlayer → StarterPlayerScripts)
local ts = game:GetService("TweenService")
local rs = game:GetService("RunService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character
local selector = game.ReplicatedStorage:WaitForChild("Selector")
local interacts = {}
repeat wait() until game:IsLoaded()
for i, v in pairs(workspace:GetDescendants()) do
if v:FindFirstChild("Interactable") and v:IsA("BasePart") then
table.insert(interacts, v)
end
end
print(interacts)
for i, v in pairs(interacts) do
local clone = selector:Clone()
clone.OutlineTransparency = 1
clone.Enabled = true
clone.Adornee = v
clone.Parent = v
end
function hideAll()
for i, v in pairs(interacts) do
local outline = v:FindFirstChildWhichIsA("Highlight")
if outline then
hide(outline)
end
end
end
function hide(outline:Highlight)
if not outline or outline.OutlineTransparency == 1 then return end
local info = TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.In)
local Tween = ts:Create(outline, info, {OutlineTransparency = 1})
Tween:Play()
end
function show(outline:Highlight)
if not outline or outline.OutlineTransparency == 0 then return end
local info = TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local Tween = ts:Create(outline, info, {OutlineTransparency = 0})
Tween:Play()
end
rs.Heartbeat:Connect(function()
local target = mouse.Target
if not target then hideAll() return end
local targetHighlight = target:FindFirstChildWhichIsA("Highlight")
if targetHighlight and table.find(interacts, target) then
show(targetHighlight)
else
hideAll()
end
end)
Any help appreciated! (like I said, I know how to fix this issue, I just want to know why is it happening in the first place)
Ok, so every heartbeat after the mouse loses the target block hideall is run, in turn creating a new tween with a 0.2 duration from the starting transparency, which has only had around 16ms to run and fade the tween.
Each tween is cancelled each time and a new one created, to resolve the conflict, which is fine but it takes time, and when this happens every single heartbeat it adds up.
Yes, ideally you only want to call the tween once. Also you only need to hide those with highlights, not everything in the interacts table.
I would:
Create a new empty table.
Change the show function so it adds the object to the table.
Change the hideall function to loop through the new table.
Change the hide function to remove the object from the table.
Change the heartbeat function to find objects in the new table instead of interacts.
Sounds like a lot, but it should only be one or two line changes for each.
It should only check for objects with active highlights once and hide them once.
I tried changing the script to fit what you just said. (I decided to do it 'cuz the game was laggy)
Have I done it right? Do I need to change anything?
local ts = game:GetService("TweenService")
local rs = game:GetService("RunService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character
local selector = game.ReplicatedStorage:WaitForChild("Selection"):WaitForChild("Selector")
local current = selector.Parent:WaitForChild("CurrentSelect")
local oldSelect = nil
local interacts = {}
local visible = {}
repeat wait() until game:IsLoaded()
task.spawn(function()
while task.wait(5) do
for i, v in pairs(workspace:GetDescendants()) do
if v:FindFirstChild("Interactable") and v:IsA("BasePart") then
if not table.find(interacts, v) then
table.insert(interacts, v)
end
end
end
print(interacts)
for i, v in pairs(interacts) do
if v:FindFirstChildWhichIsA("Highlight") then continue end
local clone = selector:Clone()
clone.OutlineTransparency = 1
clone.Enabled = true
clone.Adornee = v
clone.Parent = v
end
end
end)
function hideAll()
for i, v in pairs(visible) do
local outline = v -- :FindFirstChildWhichIsA("Highlight")
if outline then
hide(outline)
end
end
current.Value = nil
end
function hide(outline:Highlight)
if not outline or outline.OutlineTransparency == 1 then return end
local info = TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.In)
local Tween = ts:Create(outline, info, {OutlineTransparency = 1})
Tween:Play()
for i, v in pairs(visible) do
if v == outline then
table.remove(visible, i)
end
end
end
function show(outline:Highlight)
if not outline or outline.OutlineTransparency == 0 then return end
local info = TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local Tween = ts:Create(outline, info, {OutlineTransparency = 0})
Tween:Play()
table.insert(visible, outline)
end
rs.Heartbeat:Connect(function()
local target = mouse.Target
if not target then hideAll() return end
local targetHighlight = target:FindFirstChildWhichIsA("Highlight")
if targetHighlight and table.find(interacts, target) then
--print("Selectable object found!")
--print(player.Character)
if player.Character then
local distance = (target.Position - player.Character.PrimaryPart.Position).Magnitude
--print(distance)
if distance < 10 then
if oldSelect then
local oldHighlight = oldSelect:FindFirstChildWhichIsA("Highlight")
hide(oldHighlight)
end
current.Value = target
show(targetHighlight)
else
hideAll()
end
else
hideAll()
end
--[[
if oldSelect then
local oldHighlight = oldSelect:FindFirstChildWhichIsA("Highlight")
hide(oldHighlight)
end
current.Value = target
show(targetHighlight)
]]
else
--print("No selectable object found. Unselecting all...")
hideAll()
end
oldSelect = current.Value
end)
mouse.Button1Up:Connect(function()
if current.Value ~= nil then
current.Parent:WaitForChild("InteractInit"):FireServer(current.Value)
end
end)
(Please note that I continued the script with interactions, so it’s a bit more than the original)