Any tips to improving this? (Tweening on hover)

Only question I have is if I’m using :Connect properly or not, as I’ve never seen someone use it like I have. Any other advice helps.

local TweenService = game:GetService("TweenService")

function TweenColor(Object, Color)
	return function()
		TweenService:Create(
			Object,
			TweenInfo.new(
				0.25,
				Enum.EasingStyle.Linear
			),
			{
				BackgroundColor3 = Color,
			}
		):Play()
	end
end

for i,v in pairs(script.Parent:GetChildren()) do
	if v:IsA("TextButton") then
		v.MouseEnter:Connect(TweenColor(v, Color3.fromRGB(191, 9, 9)))
		v.MouseLeave:Connect(TweenColor(v, Color3.fromRGB(48, 48, 48)))
	end
end
5 Likes

Seems like a good use case of closures since you are keeping the state of the paramaters. Good job. :wink: Too bad I won’t be able to write an essay ;((

4 Likes

It looks really good! Another addition you can try is caching the tweens so if the same parameters are passed again, you can just return the already created tween. Nice job!

2 Likes

How would I go about doing that?

2 Likes

Since you aren’t using the i variable, I believe you should do _, v. It keeps Roblox from creating another variable, at least that’s what I was told once.

2 Likes

Hmm, this might not be the best way to do this but you can use a table where the objects are keys and the values are tables. Example:

local cachedTweens = {
    [guiObject]   = {
        [Color3] = TweenObject
    }
}

this is what’d it look like, you’ll have to add the keys and values when the function is called. And then you can check if the object exists within the table and if the color exists in the table as well.

2 Likes

Went through all my scripts that don’t use i and fixed them. Thanks!

3 Likes

roblox still caches the value of the key in _, it doesn’t matter if the name is different. It’s something that keeps your code organized

3 Likes

I’ll start implementing this, thank you!

1 Like

Actually it looks like this function is solely made for your gui buttons I’d recommend doing this instead. (If not then ignore this.)

for i,v in pairs(script.Parent:GetChildren()) do
	if v:IsA("TextButton") then
        local tweenEnter = TweenService:Create(...)
        local tweenLeave = TweenService:Create(...)
		v.MouseEnter:Connect(function return tweenEnter:Play() end)
		v.MouseLeave:Connect(function return tweenLeave:Play() end)
	end
end

Now, I’m unaware if there are any performance differences from using an anonymous function and predefined one so don’t quote me on that.

3 Likes

it doesn’t, if that was the case we would be able to access _ which we can’t do.

local _ = 3
print(_) -- doesn't print 3
3 Likes

it’s still a throwaway variable, doesn’t get gc’d instantly.

2 Likes

why would the variable need to be gc’d if it doesn’t have a reference? The variable isn’t allocated in memory since it isn’t accessible. @Autterfly -san any idea on whether or not I’m correct ;-;

2 Likes

Using _ doesn’t make it a special variable like haskell.

From: lua-users wiki: Lua Style Guide
In Lua, " _ " is only a convention with no inherent special meaning though.

Correct me if I’m wrong, since I’m not 100% sure about all this.

2 Likes

No, it doesn’t prevent it from declaring another variable. People only use _ for readability purposes. It just shows the reader that you aren’t going to use the variable.

4 Likes

Since the variable is allocated on the stack, it will only be cleared when that stack or scope ends assuming it has no strong references.

Even when it has strong references, it still be cleared.

local a = "b"
local b = a -- strong reference to a

--[[
   stack or scope ends, a cant be cleared since it has a
   strong reference, but b will be gced since it doesn't have any strong references.

   b is cleared
   now a doesn't have strong references (b was nil)
   a is cleared

]]

And no, you can access _, that is just a naming convention people use to show unneeded variables.

Proof:

3 Likes

It’s pretty good.

I made something really overcomplicated just because I was bored so you can possibly see if you wanna add something from this:

-- << Services
local Tween = game:GetService("TweenService")

-- << Custom Button Events
local Info = TweenInfo.new(.25, Enum["EasingStyle"].Linear)
local tweenColor = function(Button, Color)
	return Tween:Create(Button, Info, {BackgroundColor3 = Color})
end

local Colors = {
	Enter = Color3.fromRGB(191, 9, 9),
	Leave = Color3.fromRGB(48, 48, 48)
}
local Cache = {
	Enter = {},
	Leave = {}
}

for _, Button in next, script.Parent:GetChildren() do
	if Button:IsA("TextButton") then

		Button.AutoButtonColor = false
		for _, Event in next, {"Enter", "Leave"} do
			local Cached = Cache[Event]
			Cached[Button] = tweenColor(Button, Colors[Event])
			Button["Mouse" .. Event]:Connect(function()
				Cached[Button]:Play()
			end)
		end
	end
end
2 Likes

This is amazing, I was half way implementing this and I was running into some problems but this helps me understand it better.

I did notice though that you’re using in next instead of in pairs? Is there a particular reason or is it just preference.

You should try giving examples that are simpler to understand, as this is bad practice to do so many steps just to tween things. If you are going to give so many steps, add comments so someone can read and understand your code more.

Best, TheROBLOXMAPMAKE :smiley:

pairs is just next but with a paranthesis

function pairs (t)
   return next, t, nil
end

ipairs seems more suitable in op’s code because ipairs iterates in order and is slightly faster (the speed difference is very small)

1 Like