Frames are rendered at previous position when Visibility is enabled

PC Info: Windows 11, 22621

Date First Experienced: 4/14/2024
Date Last Experienced: 4/14/2024

Issue: Upon changing the Visibility of a Frame, the previous rendered position gets rendered again.
Reproduction Steps:

  1. Create a ScreenGui in StarterGui & Insert a Frame
  2. Insert a LocalScript under the ScreenGui, with this code:
local frame = script.Parent.Frame
local elapsed = 0

while true do
	local deltaTime = game:GetService('RunService').RenderStepped:Wait()
	elapsed += deltaTime
	
	if (elapsed > 1) then
		elapsed = 0
		frame.Position = UDim2.new(0.5, 0, 0.5, 200)
		frame.Visible = true
		
		print('visibility set to true, offset:', frame.Position.Y.Offset)
		task.wait(1) -- // to better visualize the bug
	elseif (frame.Visible) then
		warn('moved back to center and set visible to false')
		frame.Visible = false
		frame.Position = UDim2.fromScale(0.5, 0.5)
	end
end
  1. Play-test and observe the Frame bug.

Video of the bug:

Notes:
This bug only occurs when connected to RenderStepped or PreRender.
It seems like the __newindex call is delayed by one frame.

Expected behavior

Expected behavior: Frame will render at the current position, not the previous position.

7 Likes

I’ve been noticing a very similar issue since last week. RenderStepped, PreRender and metatables don’t seem to impact the behavior at all in my case. The issue doesn’t always happen either, but when it does happen it is very consistent.

Below is a video of a character select I created. When I select a locked character I toggle the visibility of a green purchase button. You can see that as soon as it becomes visibile that for one frame its location and size are wrong. You may have to play the video at a lower speed to even notice the issue.

On top of the ‘teleporting’ issue the text inside the green button also becomes smaller than it should be despite TextScaled being set to true. Originally I thought this problem was related to the UIFlex beta being used, but the issue Trooper reported here seems extremely similar to mine despite not using any of the UIFlex beta features in their repro steps.

2 Likes

I’m able to reproduce this much more frequently in plugins. Making plugins visible cause elements to render in a previous position for one frame. It’s more prominent with text being unaligned and out of the TextBox for one frame.

1 Like

Thanks for the report! We’ll follow up when we have an update for you.

1 Like

Hi @Troopermaan - thanks for the report! We will investigate this and hopefully have a resolution soon.

3 Likes

Hi, while we are internally investigating and working on a fix, do you mind using the following method:

local frame = script.Parent.Frame
local elapsed = 0

while true do
	local deltaTime = game:GetService('RunService').RenderStepped:Wait()
	elapsed += deltaTime
	
	if (elapsed > 1) then
		elapsed = 0
		frame.Position = UDim2.new(0.5, 0, 0.5, 200)
        _ = frame.AbsoluteSize  -- <- Adding this line would force frame to go to expected position on time.
		frame.Visible = true
		
		print('visibility set to true, offset:', frame.Position.Y.Offset)
		task.wait(1) -- // to better visualize the bug
	elseif (frame.Visible) then
		warn('moved back to center and set visible to false')
		frame.Visible = false
		frame.Position = UDim2.fromScale(0.5, 0.5)
	end
end

Thanks.

2 Likes

Hi @Troopermaan ! Just wanted to follow up if you had a chance to try out the workaround suggested by @0xabcdef1234 ?

1 Like

Yes, it works. However, it is a very hacky solution, so I still would like to see a proper resolution. :smiley:

1 Like

I’m still experiencing this problem.
Setting a frame’s visibility to true always makes it show up at it’s last position when it was turned invisible for a split second before going back to it’s new current position.

are you using the deferred signal behavior and change the visibility during render stepped connections? Do you mind change signal behavior for immediate and check if this issue still happens for you? Thanks

Hello!
Sorry this was a mistake on my end. Apparently the position of the UI was only updating if the UI was visible, and I was setting the visibility after updating the position.

Hey there! This is still an issue and is not fixed.

As you suggest, this only happens on Deferred signaling behavior and is not a problem when signaling is set to Immediate, but that’s not exactly a solution, especially since Deferred signaling is the one being pushed as the future standard.

Indexing for the AbsolutePosition property of the frame after updating its position also fixes this on Deferred mode, but this is a hacky solution. Swapping from RenderStepped to Heartbeat also fixes this problem on Deferred mode.

So seems like this only happens on RenderStepped when deferred signaling is enabled?