Introduction to Tweening Models

I just had to get a little bit creative with how I use CFrames, thanks for the response though it was helpful, I’ll avoid tweening position in the future.

1 Like

This was a great tutorial and was very helpful into understanding how welds and tweens work. I have never been fond of object oriented programming due to its complexity towards my mind but, this tutorial made it simple and easy to understand.

Hey developers! Coming by with an important update.


First, let's start with the cool thing.

…I’ve finally gotten around to adding a table of contents, woohoo! It’s right at the top of the thread before the introduction so now you can jump to parts of the tutorial rather than having to scale the entire thing to find a point or to get right to the good parts. This was a long time overdue.

I still do recommend that newer developers read up until Section 5 to fully understand what we’re doing and how to do it. The rest of the thread is more relevant to developers familiar with SetPrimaryPartCFrame versions of tweening models since it tackles the problems around it. If you’re only just learning how to tween (models), don’t worry too much about the rest. :smiley:


Next: time to clear up physics exploits.

(I think I already addressed this well in the original post that they’re still okay but you need specific implementations to combat exploiters and therefore I wouldn’t do a writeup on it. This is just double clarification in that regard.)

Previously, I marked a post I created explaining that you should avoid physics (constraints specifically) as an alternative to welding and tweening a root part. That post is available as post 14: if you need a quick reference to the post in question, look no further:

I am happy to tell you all that you do not actually need to avoid constraints and there are ways to combat these exploits.

I admit that initially I did not have sufficient knowledge on physics and their relation to exploiting so I made a “reasonable” explanation as to why I would avoid writing on constraints. After delving further into the matter and discussing it with another developer, physics are actually safe to use as an alternative for tweening if you want player force to influence the movement of a door. For example, a wild west type game where saloon doors can fling open when the player runs through them.

Roblox supports a lot of physics control. While indeed the issue in the video was a result of a network ownership exploit, the reason it was possible was because the game was badly architectured. If you don’t know what you’re doing it can be a problem but it’s not too hard to resolve either. As parts network owned by a client replicate physics, the server is able to act as a point of truth.

Generally, the method to combat this exploit is as such:

  • Check reasonably frequently, maybe in Stepped (assuming automatic network ownership transfers ownership after physics are simulated), between a set of doors actively being interacted with where they are in the Workspace. You may need to define a space that identifies where the door should be (e.g. a small, invisible, non-collidable part in the middle of the threshold).

  • How far are the doors away from this threshold? If they are unreasonably far or outgo any other defined boundaries, check who the current network owner is and kick them or flag them down as a potential bad actor and kick them if more doors are unreasonably displaced by the same network owner (~3 times, batch all checks - don’t flag them per door, rather per physics step).

  • Have the server reset the position of the doors and claim network ownership briefly. As the server is authoritative of all actions and can override the client, the doors will be appropriately placed back in the locations they should have been in and it’ll update for everyone else.

Knowing this, you can still use constraints to manage door physics and developers in fact still do in games with large traffic. That being said, the sad part, I will still not be revisiting the section describing how you can opt to use constraints for a door system. As this is meant to be an all-purpose tutorial for tweening models, physics would be out of the scope of this tutorial.

tl;dr Constraints are okay to use for doors, but the reason I will not be writing up a section on constraints has changed from “exploiter problems” to “out of the scope of this tutorial”.


That’s all fellas. Happy developing!

7 Likes

I followed this exact way, except for one problem: welded parts don’t follow the primary part on the server.

On the client, it works perfectly fine, but on the server, it doesn’t. For any new players who join the game while the tween is moving, the welds get messed up and welded objects get misplaced.

Here is an example using a tweened elevator:

4 Likes

I will need far more details if you’re looking for help resolving this. I can’t offer help based solely on a video and your word that you’re following the tutorial because this otherwise should not be an issue.

1 Like

Well it wasn’t exactly your way but the same concept, the main mover part is anchored and everything else is unanchored, welded to the main mover part. I made a post for support but it hasn’t been solved yet.

1 Like

How would i use this guide to make an elevator? it has been almost 1 year since i last tried and i finally got the confidence to make one for my game.

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