Introduction to Tweening Models

For elevators I typically recommend using constraints. That is, you can still rig your elevator the same way I have but make use of PrismaticConstraints instead. Ideally this also means that your root part will be unanchored and network ownership needs to be given to the server.

If you’re following this tutorial directly, then your tweens would be along the Y-axis.

1 Like

Ok. thank you for explaining.

i need more characters so i am just saying hi.

How do I tween the rotation of a model, I’ve tried using CFrame.Angles(0,math.rad(0),0) [obviously chaging the numbers] and CFrame.fromEulerAnglesXYZ(0,0,0) with the correct code behind it, presented by tutorials, but to no avail, since nor the primary part or the other parts in the model rotate at all.
When I use {Orientation = Vector3.new} the primary part rotates just fine, but the other parts in the model rotate so in such an extreme fashion, that it’s just wrong. To be clear, the parts are unions, and there are only 4 unions in the entire model. not to big either.

I’ve read the tutorial all the way through but none of it tell’s me how to tween rotation in a model, other than using a hinge part. Is there a way to have the model rotate on its primary part while tweening the rotation or do I have to use a hinge part?

PS: I’ve also tried using align position and align orientation but it did not work.

The samples in the thread all work with PrimaryParts. For the rotation example, the hinge is the PrimaryPart. The reason why I preferred using a hinge is because I don’t have to figure out any offsets myself. Rotations naturally occur at the center of a part, so the hinge simply represents a convenient rotatable root that maintains the same center position.

As far as rotation examples go, it’s there in the thread. If by PrimaryPart you were asking for how you can rotate a model at a point without a hinge part as your root, then it’s up to you to add an offset and define a point of reference to rotate around. I’m personally not good with CFrames which is why I opt to use something convenient for my use case.

I will need explicit details about your current circumstances if you’re looking for help, especially in terms of the rigging structure and such of your model. Issues like this require visuals and data in order to be easier to resolve; words alone don’t sufficiently convey the problem.

Another note: given that the new pivot APIs were released, you can also make use of the old method of CFraming. You would just need to adjust the pivot in place of where you’d put the hinge and then apply your rotation angularly (PivotTo every frame, Changed is kind of ugly for this).

Hmm, well in that case. How exactly do you recommend that I can add a point of reference to the model, or use a PivotTo?

This computer isn’t my computer, since I sent mine for repairs (it’s decommissioned) so I shouldn’t take screenshots since the storage on this computer is pretty much full , and full of important documents, however i’ll see if a screenshot fits in this bad boy.

I can tell you that the model is a door, I have two of them, each model has only 4 unions, so 8 unions total to tween. The tween script is a server script, outside the models in explorer, but the variables are assigned correctly. The tween moves the unions correctly, but rotation is failing on me, i just want to spin the model 90 degrees, or π/2 radians.
I relatively seasoned when it comes to using CFrames, but I don’t get why when using:
RightDoor.PrimaryPart.CFrame = CFrame.Angles(0,math.rad(3.14159/2),0)
Nothing happens at all. And it worked for a separate part and script, whats going on?

PS: Lol a screenshot fit
PPS: The orientation part has been reverted, since it was the only line that somewhat worked.

3 Likes

Before I do continue, I should note: CFrames are comprised of a positional and rotational value. Something that you may find trouble with is running two different tweens on the same part because one can override the other.

In your specific case you should be running one tween where any goals that need to be tweened on a part are all written to one table. That’d mean that CFrame and Orientation, although the former overwrites the latter, should have been in the same goals table for one CFrame.

Thanks for the question though! I think I’ll write up an additional section on this tutorial about using pivots to tween models and its benefits over the SetPrimaryPartCFrame version.


I’m not deeply acquainted with CFrames so finding a point of reference is up in the air. It would require moving to world space, getting a rotation goal and just a lot that I’d prefer not to think about. I primarily had novices in mind while designing this tutorial.

Personally if you really wanted to avoid using a hinge part to serve as your center of rotation and preferred to just work with a different PrimaryPart, you could use pivots as your reference point and then PivotTo. This would require returning to the old method of tweening models primarily because they account for variables inaccessible to the developer outside of Studio (pivot offset specifically).

Pivots would actually make this easier since they themselves can act as your point of reference. It’s ideal to still have a PrimaryPart but this appears in tune with your current problem so I can dive right into showing rotation with a pivot.

I did not save the original model I used in the tutorial so I’ll just bootleg it. Say hello to our new glass door™, a model where the PrimaryPart is set to the bottom of the door.

That blue-outlined white dot that’s appearing at the center of the bottom of the door, or the PrimaryPart, is the pivot. Roblox’s new pivot editor should allow you to redefine where this is positioned and rotated. Pivot points are powerful because they can help determine across where the model should be rotated. You can keep it at the bottom but just move it towards a point you want it to rotate across.

Here I’ve set my pivot to the edge of the door where a hinge part would normally be. This will be where my part rotates around. From there, we need to write a different piece of code that will get the pivot’s current CFrame, angle it and then pivot it to the goal. Since TweenService requires an instance to tween we’ll use a CFrameValue to simulate the change.

local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")

local Panel = workspace.Panel

local function tweenModel(model, tweenInfo, offsetCFrame)
	local modelPivot = model:GetPivot()
	local steppedConnection
	
	local CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = modelPivot
	
	steppedConnection = RunService.Stepped:Connect(function ()
		model:PivotTo(CFrameValue.Value)
	end)
	
	local tween = TweenService:Create(CFrameValue, tweenInfo, {Value = modelPivot * offsetCFrame})
	tween.Completed:Connect(function ()
		steppedConnection:Disconnect()
		CFrameValue:Destroy()
		tween:Destroy() -- Avoid memory leak from tween
	end)
	tween:Play()
end

This function takes three parameters to use:

  • model: Model → The model that you want to tween.
  • tweenInfo: TweenInfo → A TweenInfo object that you want passed for the model tween.
  • offsetCFrame: CFrame → A CFrame that your item should be offset by. You can evaluate CFrames (e.g. CFrame.new * CFrame.Angles), just needs to be one CFrame in the end.

If you wanted this to be reusable, a good fit would be turning this into a ModuleScript and adding return tweenModel at the end. You can then require it and use it as a function whenever:

local tweenModel = require(path_to_module.TweenModel)
local tweenInfo = TweenInfo.new() -- Use all defaults

tweenModel(model, tweenInfo, CFrame.Angles(0, math.rad(180), 0))

Even if you didn’t want to use it as a ModuleScript and just put the function in your code, the function call would still work the same way. In terms of the offsetCFrame, you just need to describe how you want the door rotated. The function will calculate the pivot’s offset for you itself so that you don’t have to write like, Model:GetPivot() * CFrame for the last argument. In this code example I’m just passing a CFrame with RX 0, RY rad(180) and RZ 0; the function translates this to “rotate the model 180 degrees (in radians) around the pivot”.

Note that since Studio mode does not simulate physics unless you are in a test mode that spawns a local server you will not be able to test how it looks while in editing mode.

Let me know if you have any questions or if you need further support!

12 Likes

Right then i’ll see what happens tomorrow (currently 10:00 pm where i’m at, and my schedule is a bit tight) I’ll replace my original work with a pivot point or part, depending which one flushes out better, I’ll send a personal reply as to not fill up this forum and block any other question from another developer.
Even being an Amatuer-Pro programmer, this is actually a different world of tweening for me, ought to be interesting, and nice tutorial bro.

No prob, lol

1 Like

How come when i run this code

wait(20)
local TweenService = game:GetService("TweenService")

local Panel = workspace.Door1
local PanelRoot = Panel.PrimaryPart

local PanelSlideInfo = TweenInfo.new(5) -- Let's use all defaults here

local PanelSlideTween = TweenService:Create(PanelRoot, PanelSlideInfo, {
	CFrame = PanelRoot.CFrame * CFrame.new(0,5,0)
})

PanelSlideTween:Play()

it gives an error of: 16:32:21.433 Workspace.Door1.Script:10: attempt to index nil with ‘CFrame’ - Server - Script:10

1 Like

Does the Panel have its PrimaryPart set?

One question i have is do you still use a hinge when you want the door to slide / move up and down?

Yes, I still use hinges and reference points for vertical and horizontal translations as well. The only difference there is that you’re changing the position instead of the orientation of the model.

1 Like

Hmm I thought it ment when it said a bounding box to make a part inside the model and make it the primary part but im still confused do i link the hinge to the bounding box then the model? Or is it diffrent?

Bounding box is the easiest way to do it but you can also use a hinge part lined up in any way to get the part to move. For translations it doesn’t matter so much as it does for orientations because ideally when rotating you want the hinge to stay in relatively the same place and rotate it by a corner rather than by another awkward angling.

Bounding box for translations is the same as the hinge part for the purposes of the tutorial, just that the operations being performed on them differs (translations vs orientations).

3 Likes

This method seems not working for rotating model.

it does work, you just didn’t do it correctly.

Is there any video clip online about how to achieve that?? :sweat_smile:

The tutorial itself shows you how to do it…?

Tween Info’s are not dynamic so when you want it to go back to its original position for closing you should just do

local DoorClose = TweenService:Create(Model.PrimaryPart, PanelSlideInfo, {CFrame = Model.PrimaryPart.CFrame}
1 Like

How so? The only way that I can find out on how to change the position of the model is through the Model:PivotTo(CFrame) function. I’m questioning how WOULD I tween it using this function and without using welds. I tried to change the WorldPivot property, but that just changes the position of the pivot itself and not bringing the whole model.

This is in documentation - WorldPivot changes the position of the pivot. Pivot properties only modify the coordinates of the pivot, PivotTo will bring along a model with the pivot’s coordinates in mind so that’s what you need to be using.

I made a brief note at the top of the OP explaining that PivotTo is appropriate to use with the legacy method if you’re looking for something convenient. PivotTo can be used as a drop-in replacement for SetPrimaryPartCFrame assuming the same setup and the pivot point being in the center of the primary part but the same will not go for changed pivots.

I’ve yet to modify the tutorial to accommodate pivots so I left that note at the top. I’ll probably find some time in the future to make sure the tutorial covers that option as well.

1 Like