Part orientation not being consistent

Hello, I’m trying to make a sectional door by making the panels point to attachments that are being positioned throughout a path. For some reason, the panels orientate themselves to the side briefly then return to normal. What could be causing this and would there be a better way to approach what I’m trying to do? I’ve been stumped at what could possibly be an easy fix for a bit too long now. If more information needs to be provided, let me know. Thanks.

The issue:

The code:

local speed = Garage.Config.Speed.Value
	-- ...
	for i, panel: part in pairs(Garage:GetChildren()) do
		if panel.Name:find("Panel") and not panel.Name:find("Group") then
			task.spawn(function()
				-- ...
				local Bottom = group.Lower
				local Center = group.Middle
				local Top = group.Higher
				while true do
					if (panel.Top.WorldPosition.Y < group.MiddleGuide.WorldPosition.Y) and not tweening then	
						panel.CFrame = panel.CFrame+Vector3.new(0,0.02*speed,0)
					elseif ((panel.Top.WorldPosition.Y >= group.MiddleGuide.WorldPosition.Y) or tweening) and not finished then
-- Positioning the Attachments V
						if not tweening then
							tweening = true
							task.spawn(function()
								local t = TS:Create(Bottom, TweenInfo.new(1/speed,Enum.EasingStyle.Linear),{WorldCFrame=Garage.DefaultGroup.Union.MiddleGuide.WorldCFrame})
								t:Play()
								t.Completed:Wait()
								for _, curve in ipairs(Garage.Curves:GetChildren()) do
									local t = TS:Create(Bottom, TweenInfo.new(0.12/speed,Enum.EasingStyle.Linear),{WorldPosition=curve.Position})
									t:Play()
									t.Completed:Wait()
								end
							end)
							task.spawn(function()
								for _, curve in ipairs(Garage.Curves:GetChildren()) do
									local t = TS:Create(Top, TweenInfo.new(0.12/speed,Enum.EasingStyle.Linear),{WorldPosition=curve.Position})
									t:Play()
									t.Completed:Wait()
								end
								local t = TS:Create(Top, TweenInfo.new(1/speed,Enum.EasingStyle.Linear),{WorldCFrame=Garage.DefaultGroup.Union.HigherGuide.WorldCFrame})
								t:Play()
								t.Completed:Wait()
								finished = true
							end)
						end	
-- Positioning the Attachments ^
-- The main stuff V
						local posA = Bottom.WorldPosition
						local posB = Top.WorldPosition
						local newPos = (posA+posB)/2
						local newCFrame = CFrame.new(newPos,posB)
						Center.WorldCFrame = newCFrame 
						panel.CFrame = Center.WorldCFrame 

					elseif finished and not reachedEnd then
						-- ...
						end
					end
					task.wait(0.01)
				end
			end)
		end
	end
2 Likes

I watched the video, everything works fine until that little bevel on the corner part of where it ascends.

Where is the attachment parented? They can be a bit confusing at times when it comes to positioning, as it’s entirely relative to the parent. I’m thinking you’re parenting it to something that’s already moving, therefore causing this weird effect.

1 Like

The attachments that are being moved and not are parented to an anchored part in another group and that part isn’t being moved. The “curve” parts are also in a separate group and not moving, their positions are only being read.
These are the attachments being used, the “guide” attachments are only used as markers for where the others should end up.
image

Could you comment out this portion:

-- Occurs right before the
-- "elseif finished and not reachedEnd then"

local newCFrame = CFrame.new(newPos, posB)
Center.WorldCFrame = newCFrame
panel.CFrame = Center.WorldCFrame

See if this makes it not snap 90-degrees, it could be that the front face of your baseparts are on the sides of it, and when you do CFrame.lookAt(posA, posB) it forces it to turn 90 degrees since it formats the CFrames default upvector to be relative to Vector3.yAxis.

If this is the primary issue, I assume you can just multiply the CFrame by an angle of CFrame.Angles(0, math.pi * 0.5, 0) and it should correct the snap.

The front of the panels were on the top side, so I adjusted them so they are actually in the front now. Commenting out that portion did make it stop the snapping, but adjusting panel.CFrame is also the only thing positioning the panel when making that turn.
I replaced my CFrame.new with CFrame.lookAt(posA, posB)*CFrame.Angles(math.rad(90), 0, math.rad(180)) so it can orientate it correctly and also using the math.pi but it didn’t really do much, and also that the positioning of the panel was off-centered when it was turning the curve after I changed it.
Using lookAt also does change it slightly and it makes the snapping issue last for a fraction of the time when making a new CFrame.

By a fraction, is it like a singular frame (0.01s)?

If it is that my only guess for that would be due to the look direction being parallel to Vector3.yAxis on that single frame or calculation.


Potential Alternatives:

To remove any unknown calculations done, you could try using CFrame.fromMatrix to force the orientation throughout the curve. Or another option is when you get to the curve, you could tween the panel’s CFrame from initial to flat with the duration being how long it takes for the panel to go around the curve.

1 Like

CFrame.fromMatrix seemed to solve it. Thank you very much!

local posA = Bottom.WorldPosition
local posB = Top.WorldPosition
local newPos = (posA+posB)/2
local lookVector = (posA-posB).Unit 
local modelUpVector = Vector3.new(0, 1, 0)
local rightVector = lookVector:Cross(modelUpVector)
local upVector = rightVector:Cross(lookVector)
local newCFrame = CFrame.fromMatrix(newPos,rightVector, upVector)*CFrame.Angles(math.rad(90),0,0)					
Center.WorldCFrame = newCFrame