How to tween a model

The problem

I want to tween an elevator cabin. But models don’t have a position property

What I came up with

Tweening the individual parts but the script doesn’t like it (It’s a localScript)

2 Likes

The legendary @colbert2677 made a tutorial on this that you can read:

3 Likes

you can use a pairs loop:

for i, v in pairs(Model:GetChildren()) do
    -- Tween
end
1 Like

Model:SetPrimaryPartCFrame if you have a PrimaryPart set will work and doesn’t require welding and will even allow you to choose the rotation aswell.
Model:MoveTo Will work if you don’t have a PrimaryPart, though it will require all parts to be welded together and will move the model upward if something is in the way.
Model:TranslateBy works if you just want to translate the position of a model and not outright set its position. This works without a PrimaryPart and without the parts being welded together.

Let me know if this helps, I just decided I would answer since I got a new keyboard for Christmas and wanted to type something out with it.

Edit: Some code samples for using these:

RunService = game:GetService("RunService")

-- this function is good for tweening to a target location. It will yield until it does.
function TweenModelToCFrame(Model, TargetCFrame, TravelTime)
--	warn if there is no PrimaryPart set and then abort.
	if not Model.PrimaryPart then warn("Model must have a PrimaryPart set.", Model) return end
	
	local StartTick = tick() -- the time we started tweening at.
	local StartCFrame = Model.PrimaryPart.CFrame
	
	while true do
		RunService.RenderStepped:Wait() -- wait a frame
		local SecondsElapsed = tick() - StartTick
		local Alpha = SecondsElapsed / TravelTime -- our percentage of the way to our target (0 to 1)
		local CurrentCFrame = StartCFrame:Lerp(TargetCFrame, Alpha) -- returns a CFrame part-way between StartCFrame and TargetCFrame with percentage Alpha.
		Model:SetPrimaryPartCFrame(CurrentCFrame)
		
		if (CurrentCFrame.Position - TargetCFrame.Position).Magnitude < .1 then
			Model:SetPrimaryPartCFrame(TargetCFrame)
			break
		end
	end
end

-- This function is good for continually moving in a direction forever.
function ContinuallyTween(Model, DirectionToTween, StudsPerSecond)
--	This function doesn't require Model.PrimaryPart
--	the infinite loop below would cause this function to yield forever. We use a coroutine to avoid this.
	coroutine.wrap(function()
		while true do
			local DeltaTime = RunService.RenderStepped:Wait() -- wait a frame and get how long that frame took.
			local StudsToTravelThisFrame = StudsPerSecond * DeltaTime
			
--			use Unit so the length of the DirectionToTween vector3 will be ignored and only its direction used.
			Model:TranslateBy(DirectionToTween.Unit * StudsToTravelThisFrame)
			
		end
	end)()
end

Examples of how to use these functions:

For continually tweening a model in a set direction forever:

Model = workspace.Model
ContinuallyTween(Model, Vector3.new(0,1,0), 2)

For tweening a model to a set destination:

Model = workspace.Model
TweenModelToCFrame(Model, CFrame.new(0,10,0), 5)

An elevator that moves up and down:

while wait() do
	TweenModelToCFrame(Model, CFrame.new(0,10,0) * CFrame.Angles(0,math.rad(90),0), 5)
	TweenModelToCFrame(Model, CFrame.new(0,0,0), 5)
end

It’s worth noting that these methods don’t move characters with them. When moving up and down this isn’t an issue but when moving side-to-side, the platform will move out from under the player. If you want to fix this, you should use physics to move your elevator with something such as a BodyPosition.

3 Likes

I encourage you to read the forum I wrote on model tweening which @return_end1 gratefully linked here.

Don’t use SetPrimaryPartCFrame. It generates floating point imprecisions due to the way it calculates offsets and will tear your model apart. Model tweening with welds allows you to choose rotation and position because you’re tweening only a single part and everything is following in after.

If you want a solution that moves without welds and anchors everything, create your own custom SetPrimaryPartCFrame function that offsets parts relative to the PrimaryPart and use that instead. I had an implementation of this somewhere but can’t find it.

2 Likes

Select all the parts for the model, and “Add to group” That will make a model. (you probably already did this.

Then in the model, you click “Primary Part” and tell it what part is the part you want to move around. Just click on the primary part in the explorer.

Then you move that part and the rest of the model follows.

I’m pretty sure that’s how it works.

@colbert2677 I was unaware that SetPrimaryPartCFrame would do that. I will admit I haven’t really used it very heavily and just tested the code samples I gave.
@Steve_Speedy you would have to weld all the other parts to the primary part for that to work. Like I said above, SetPrimaryPartCFrame would do that, but like @colbert2677 said, that’s not optimal.