Parts don't seem to stay with the rootpart, even when welded

I am supposed to make a door that can be tweened open.
For some reason the parts of the door do not stick with the rootpart, even though they are all welded together.
How do I make this work?



Here is what keeps happening:

The door stays put instead of following the root part.
My script is perfectly fine too.


I really need help. lol
I’ve been messing with this for hours now trying to get it to work.

Pretty sure that should be in #help-and-feedback:scripting-support

3 Likes

Personally, tweening in this instance isn’t the best overall idea unless the door is un-anchored and welded together.

I personally, would look into

for i = 0, 1, 0.025 do
    model:SetPrimaryPartCFrame(part.CFrame:lerp(newCFrame, i))
    game:GetService("RunService").Stepped:Wait()
end
1 Like

Are you able to provide a repro of your door model? Your welds may not be set up properly or you may have the other parts anchored which is causing this issue. Alternatively, you can redo your door and tweening methods according to the tutorial I wrote on model tweening.

Try switching to WeldConstraints or Motor6D, unanchoring all parts except the root and tweening it again. Regular welds are rigid and are meant to hold things firmly in place.

1 Like

I’m pretty sure your issue is that welds get destroyed when the position/orientation is set on the rootpart.

Instead of tweening Orientation and Position, tween CFrame.

local TweenService = game:GetService("TweenService")
local part = script.Parent
local Info = TweenInfo.new(
    1.5,
    Enum.EasingStyle.Quint,
    Enum.EasingDirection.Out,
    0,
    false,
    0
)
local Goals = {
    CFrame = CFrame.new(-126.568,4.5,1.592)
            *CFrame.fromOrientation(0,math.rad(115.9),0)
}
local tween = TweenService:Create(part,Info,Goals)
wait(2)
tween:Play()
2 Likes

Why does this happen?

  • Basically, for lack of better phrasing, TweenService does not support models/welds natively. When you apply a Tween to a models’ PrimaryPart, the Tween doesn’t follow the rules of welds.

The Solution:

  • The solution to this problem is creating what’s called a dummy value. Hopefully you’re familiar with CFrame values, string values, number values etc. To successfully Tween your door model, you’re going to want to use a Dummy Value.
  1. Create a CFrame Value

  2. Set the Value to the starting CFrame of the door.

  3. Create a Tween that tweens the newly created CFrame value. It should look something like this…

    local tween = TweenService:Create(cframeValue, TweenInfo.new(...), {Value = WantedCFrame})

  4. Before you play you play your tween, you want to make a new connection. Connect a function to the CFrame values .Changed signal.

    cframeValue.Changed:Connect(function(newCFrame)

    Now, everytime the CFrameValue is changed from the Tween, this function will be called. When this happens, we want to set the position of the door to the newPosition

  5. To set the position of the door model, you’re going to want to set the PrimaryPartCFrame of the model.

    doorModel:SetPrimaryPartCFrame(newCFrame)

Gotchas:

  • This isn’t the most “elegant” way to tween a model
  1. If your model does not have a PrimaryPart, this will error

  2. This does create a new CFrame value everytime you tween, but is removed after the tween is completed

  3. Using CFrame values yields the chance for the other parts of the model to become slightly mis-aligned after many Tweens. If you don’t plan on tweening the door many times, and or don’t care about the change of slight mis-alignment, It’s easier to use this method.

So, our final code may look something like this. I heavily commented so you can fully understand what’s going on :slight_smile:

local tweenService = game:GetService("TweenService")
local doorModel = workspace["Wood Crate"]

local function tweenModel(model, targetCFrame, tweenTime)
	--Create the dummy CFrameValue
	local cframeValue = Instance.new("CFrameValue")
	cframeValue.Parent = model
	
	--Set the value of the CFrameValue to the starting position of the door
	cframeValue.Value = model.PrimaryPart.CFrame
	
	--Create tween
	local modelTween = tweenService:Create(cframeValue, TweenInfo.new(tweenTime), {Value = targetCFrame})
	
	--Create connection to .Changed singal
	cframeValue.Changed:Connect(function(newCFrame)
		model:SetPrimaryPartCFrame(newCFrame)
	end)
	
	--Create connection to .Completed signal (when then tween is finished playing)
	modelTween.Completed:Connect(function(playbackState)
		if (playbackState == Enum.PlaybackState.Completed) then
			cframeValue:Destroy()	
		end
	end)
	
	--Play tween
	modelTween:Play()
end
1 Like

I don’t recommend doing this at all. I actually dedicated a whole section in my above linked tutorial to talk about this and why it’s not a particularly ideal solution. Tweens do support welding, there’s no reason for them not to.

Here’s a chunk out of the thread discussing the use of SetPrimaryPartCFrame:

And you can see a ton of complaints with the function with a quick search on Platform Feedback with just the method’s name:

https://devforum.roblox.com/search?q=SetPrimaryPartCFrame%20category:10

The misalignment isn’t slight. Floating point imprecisions build up to the point where models get torn apart fully and look like an utter wreck. Depending on how many times you tween, you can find yourself in this position as well. Better to steer clear of an avoidable problem than to ignore it.

1 Like

This is why I made sure to include a Gotcha section clearly stating the ill-effects of using this method. It’s a spotty method but one that can be used.

1 Like