Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why's the GUI's position going to undesired, negative position?

To be more specific, on line 21 (see code below), the GUI's position goes to a negative position, then proceeds onto position -0.05, 0, -0.05, 0; however, line 24 is exactly how I want the code to work, from how its decreasing the size & increasing the position.

I believe it's line 12 (see code below) that's causing the problem, but I'm not very sure; I received no errors, except what the prints in the code returned, and lines 2-4 are fail-safes for when I join the studio server (F6 creates a studio-server).

This is the code I created & am using:


repeat
	wait(2)
until true

local scriptsParent = script.Parent

print('FIRED')

function TweenSize(z, x, c)
	for i = z, x, c do
		local CalculatePosition = z > 0 and z - i or i - x -- May be problem(?)
		scriptsParent.Size = UDim2.new(i, 0, i, 0)
		scriptsParent.Position = UDim2.new(CalculatePosition, 0, CalculatePosition, 0)
		wait(1 / 15)
	end
end

while true do
	print('1')
	TweenSize(0, 1, 0.05) -- Doesn't work how I want it to
	wait(5)
	print('2')
	TweenSize(1, 0, -0.05) -- Works exactly how I want it to
	wait(5)
end

I'm aware of TweenSize & Tweenposition, but I fail to see how to accomplish, like line 24, w/ them, and even if I could accomplish what I could w/ them, I want to see how it's done w/ the for loop. Ty for reading. ;)

1 comment

0

e-e

1 answer

✓ Accepted answer

A minor change that helps understanding is to give your variables appropriate names (though nothing wrong with CalculatePosition necessarily):

function TweenSize(start, finish, step)
	for size = start, finish, step do
		local pos = start > 0 and start - size or size - finish
		scriptsParent.Size = UDim2.new(size, 0, size, 0)
		scriptsParent.Position = UDim2.new(pos, 0, pos, 0)
	end
end

Now it is easier to analyze the line local pos = start > 0 and start - size or size - finish. Why do you want different behaviour if you're starting at a size greater than 0? In the case of TweenSize(0, 1, 0.05), pos = size - finish, which starts with 0 - 1 = -1 and then continues to 1 - 1 = 0. This is why you see the behaviour you do. If pos = start - size, which would start off as 0 - 0 = 0, and then proceed to 0 - 1 = -1, which is no better. You might want to redesign that line, thinking about what you actually want to happen in the general case. (Ideally you shouldn't have to worry about whether start is > 0 or not.) I believe your "working code" is presently making it so that the Gui object sticks to the lower-right of the screen. If that's what you want, then local pos = 1 - size is all you need.

If you wanted to make your function more general you might want to split the idea of tweening the size and tweening the position. Currently you're trying to do both without any additional arguments. One possibility:

function lerp(start, goal, amount) --amount between 0 and 1
	return start * (1 - amount) + goal * amount
end
function Tween(startSize, endSize, startPos, endPos, numSteps)
	local size, pos
	for amount = 0, 1, 1/numSteps do --ex, if numSteps is 10, amount increases by 0.1
		if amount ~= 0 then wait() end
		size = lerp(startSize, endSize, amount)
		pos = lerp(startPos, endPos, amount)
		scriptsParent.Size = UDim2.new(size, 0, size, 0)
		scriptsParent.Position = UDim2.new(pos, 0, pos, 0)
	end
end

This setup is not particularly flexible (though lerp is fine) because startSize and endSize are expected to be numbers rather than Vector2s or UDim2s -- the function is assuming that you will only want to tween along a specific diagonal! If that's all you want, that's alright; otherwise it isn't difficult to use more arguments or to change their type (if you do that you'll also need to update lerp to use that type). If you use UDim2s, you can use their lerp function instead of the custom one above.

Also, do note that when using a for loop, the final iteration may not occur depending on how you set it up and rounding errors. For example, if you do for i = 0, 1, 0.3 do print(i) end, you'd get 0, 0.3, 0.6, and 0.9 (but not 1). To solve this, you might want a bit of code that places scriptsParent's Size/Position at the target values after the for loop.

However, it should be much easier to use TweenSizeAndPosition to do what you'd like (without the for loops):

--set scriptsParent.Size/Position to starting values here
scriptsParent:TweenSizeAndPosition(
	UDim2.new(1, 0, 1, 0), --endSize
	UDim2.new(0, 0, 0, 0), --endPosition
	nil, nil, --use default value for easingDirection and easingStyle
	20/15, --or however long you want this to last for
	true) --override any previous tweening
wait(20/15) --or however long the animation is supposed to last
--continue on now that the animation has finished
--OR if you want to do other things before the animation has finished, looked into the final optional argument 'callback' - provide a function of what you want to have happen after the tween is finished

4 comments

0

I tried the second code you presented; it works. :D ...But it doesn't wait before executing again. (Line 7 of the second code) (I'll explain further in my next comment)

0

I added a print to check the problem, which is set up as "print(size, pos, amount, scriptsParent.Position, ":Position", scriptsParent.Size, ":Size")", and size & pos are either 0 or 1, and do not tween: they automatically set to either 1 or 0.

0

I just tested it and it works. I used this command (for the second script): "Tween(0, 1, 0.5, 0, 30)". startSize and endSize must be different for any tweening to occur.

0

Welp, that explains it. XD Ty. :) Btw, I tried the third code, and it's working out pretty well. :)

This discussion is preserved as it was. New answers, comments, and votes are closed.