Weird script parent behaviour

I have a script in which a button with a script inside switches places with another button.
The script is running, moving its parent on its own, but still somehow manages to exchange parents, even though not coded. Here’s the script

local replacee = script.Parent.Parent.Parent:FindFirstChildWhichIsA("TextButton")
replacee.Parent = script.Parent.Parent.Parent.Options

for i, v in pairs(script.Parent.Parent:GetChildren()) do
	if v:IsA("TextButton") and v ~= script.Parent then
		v.Parent = script.Parent.Parent.Parent.Options
	end
end
-- IT ERRORS HERE BUT I THINK SOMETHING MESSES IT UP IN THE LOOP ABOVE
script.Parent = script.Parent.Parent.Parent
script.Parent.Size = UDim2.new(1, 0, 1, 0)

script.Parent.Parent.OptionsTab.Visible = false
script.Parent.Parent.OptionsTab.Parent = script.Parent.Parent.Parent.Parent.Parent
script.Parent.Parent.Parent.Parent.TabOpen.Value = false
-- 
print("making changes")

Here’s the before test state

And after
image

Completely where it’s not supposed to be for some reason.
Now I don’t know if that’s expected, a bug…?

I might also just be missing something so if that’s the case please let me know.

3 Likes

This may sound dumb, but try changing v ~= script.Parent to script.Parent ~= v.

2 Likes

Still having the same behavior

2 Likes

What is the error you are getting?

Also I am not understanding what is wrong about the before and after. The script looks like it has the correct parent in the after screenshot.

Didn’t you answer your own question? you just changed the script parent here for some odd reason.

Edit:
What is the purpose of setting the parents of all these objects anyways? It all seems to muddle the readability of your code.
You could try FindFirstAncestor() to find the first object you are looking for instead.

FindFirstAncestor(name: string): Instance

^This code above gets a reference to NORM and parents it to its sibling Options.

^This loop does basically nothing, because it’s looping over the the children of Options and parenting them to Options, which is where the already are.

^This last one moves the LocalScript itself, to be a child of GQ.

Your “after” screenshot shows exactly what the code is expected to do.

This code is probably confusing all of you as that is just a clip of the whole code, here’s all of it

script.Parent.MouseButton1Click:Connect(function()
	if script.Parent.Parent:HasTag("Setting") then
		if not script.Parent.Parent.Parent.Parent.TabOpen.Value then
			script.Parent.Parent.Parent.Parent.TabOpen.Value = true
			for i, v in pairs(script.Parent.Parent.Parent:GetChildren()) do
				if v ~= script.Parent.Parent and v:IsA("TextLabel") then
					v.Visible = false
				end
			end
			script.Parent.Parent.Parent.Parent.Parent.OptionsTab.Parent = script.Parent.Parent
			local NofChildren = 0
			for i, v in pairs(script.Parent.Parent.Options:GetChildren()) do
				v.Parent = script.Parent.Parent.OptionsTab
				NofChildren += 1
			end
			for i, v in pairs(script.Parent.Parent.OptionsTab:GetChildren()) do
				if v:IsA("TextButton") then
					v.Size = UDim2.new(1, 0, 0.948 / NofChildren, 0)
				end
			end
			script.Parent.Parent.OptionsTab.Size = UDim2.new(1, 0, NofChildren * 1 + 0.1, 0)
			script.Parent.Parent.OptionsTab.Visible = true

		end
	else
		local replacee = script.Parent.Parent.Parent:FindFirstChildWhichIsA("TextButton")
		replacee.Parent = script.Parent.Parent.Parent.Options
		for i, v in pairs(script.Parent.Parent:GetChildren()) do
			if v:IsA("TextButton") and script.Parent ~= v then
				v.Parent = script.Parent.Parent.Parent.Options
			end
		end
		script.Parent = script.Parent.Parent.Parent
		script.Parent.Size = UDim2.new(1, 0, 1, 0)

		script.Parent.Parent.OptionsTab.Visible = false
		script.Parent.Parent.OptionsTab.Parent = script.Parent.Parent.Parent.Parent.Parent
		script.Parent.Parent.Parent.Parent.TabOpen.Value = false
		-- execute game change code
		print("making changes")
	end
end)