Introduction to Tweening Models

Edit (06/30/2021): Due to the release of the new pivot APIs and the thankful deprecation of SetPrimaryPartCFrame, the legacy method of CFraming is now also appropriate and you do not necessarily need to use this welding method. Do note that the pivot CFrame is different from the PrimaryPart CFrame though, so you will have to account for that when writing your proxy objects.

Edit (05/31/2023): Roblox has an official code sample for model tweening! It’s very lightweight and covers the necessities through code comments to help guide you on how to perform model tweening yourself. Check it out on the Creator Marketplace: Animating a Model


Contents

  1. Introduction
  2. Understanding Tweening
  3. Concept of Tweening Models
  4. Rigging Your Model
    4.1. Setting Up the Root
    4.2. Attaching the Model
  5. Tweening Your Model
  6. Addressing Potential Concerns & Practices
    6.1. A Bad Legacy Method
    6.2. Using SetPrimaryPartCFrame
    6.3. Orientation of the Root Part
    6.4. Attaching Parts
    6.5. WeldConstraints
  7. Conclusion

Introduction

One of my personal favourite services on Roblox is the TweenService. Honestly, who doesn’t like some smooth transitioning in their interfaces or even just any element of their game? Eye candy is always something to appreciate, unless there’s too much of it.

Almost a year ago, I had written a tutorial titled Brief Introduction to Tweening Models. This tutorial was fairly simplistic, rushed and didn’t cover the topic as appropriately as it should’ve. Tweening models seems to be a fairly relevant topic nowadays. There’s many ways to do it, but then one of the few or only tutorials dedicated to the topic isn’t fleshed out well.

With all this in mind, I present you a new tutorial, Introduction to Tweening Models. It is the latest article that provides information for model tweening and is fit to current standards. While this is a detailed thread, I call it an introduction mostly because this describes a process to tweening models. It does not cover all possible model tweening methods and serves more as a “here’s how to get started and here are some things you should keep in mind”.

(back to top)


Understanding Tweening

For the newies here who hopped straight to tweening models rather than learning tweening as a whole, let’s define what a tween is really quickly. I’ll admit now, these are not all my words.

Tweening is the process of creating intermediate frames between two key frames. This creates a visual effect where you see something essentially glide or evolve from the first key frame to the second.

Tweening on Roblox is no different. When you see a Gui moving smoothly from point to point, that is a tween. When you see a number slowly crawl up, increment quickly and then slow down in counting upwards, that too is in fact a tween.

(back to top)


Concept of Tweening Models

Something to understand regarding tweening models is that you aren’t actually tweening a model. Might sound strange for a tutorial on tweening models, but that’s how it is. When talking about model tweening, the discussion is really about moving a model relative to a helper part.

Tweens are restricted to singular objects, especially if you’re using TweenService. Custom tween implementations are also singular, though modules that support multiple object tweens create that illusion via pseudothreading (spawn / coroutine) or iterating over a set of items.

(back to top)


Rigging Your Model

The important part to this tutorial is rigging your model. Somewhere, somehow, you require a root that will serve as the moving part for your assembly, to which all other parts will be attached to. This root can either represent your entire model, or just a hinge. The point is that only this part moves.

One of the more common use cases for model tweening may be moving a door or a casing for something, though there may be many other uses for model tweening that you may come up with.

First off, get your model. For this tutorial, I’ve constructed a model really quickly off the fly. It’s a simple panel. Our simple panel here could be turned into a solid model and we could move it as one part, but we don’t do that because we want to keep materials in.

Our panel:

(back to top)

Setting Up the Root

Start by adding a root part to this panel. This is the part we mentioned that will be the only part doing any actual moving and what we will call tweens on.

For a model that will rotate, you will need to make a hinge. This can be done by creating an invisible pole with the same width and depth, as well as the height of your model. The panel will swing around this hinge when you go to tween its rotation.

image

For a model that slides around or doesn’t need to swing, any kind of root is fine. I personally prefer a root that covers the entire model and forms a bounding box for the sake of being able to move accurately as if I’m moving the model itself, not a proxy.

Make sure that your root is rotated properly. This can affect the way your CFrame math works. Typically, what I do to confirm the positive directions of the hinge is to write a quick piece of code in my console after selecting the hinge. You must select the hinge for this to work.

local Selection = game:GetService("Selection"):Get()[1]

local NormalIds = {
	[Enum.NormalId.Top] = BrickColor.new("Lime green").Color,
	[Enum.NormalId.Front] = BrickColor.new("Really blue").Color,
	[Enum.NormalId.Right] = BrickColor.new("Really red").Color
}

for NormalId, HandleColor in pairs(NormalIds) do
	local Handles = Instance.new("Handles")
	Handles.Color3 = HandleColor
	Handles.Style = Enum.HandlesStyle.Movement
	Handles.Faces = Faces.new(NormalId)
	Handles.Adornee = Selection
	Handles.Parent = Selection
end

The above code gets arrows for the top, front and right directions, all three of which are typically used to determine positive directions in 3D space given no specification. We use these colours to help determine where our root should be rotated towards.

  • The green arrow should never be facing any other direction than the top. If so, rotate and resize the root accordingly so the green arrow points upwards. This is a concrete rule of thumb.
  • The red and blue arrows respectively must indicate a front-facing and right-facing direction. It typically doesn’t matter where these are placed, so long as your rotation axis is fine.

You can delete them once you’ve confirmed the directions of your parts are facing the right way.

(back to top)

Attaching the Model

Once you’ve decided on the root and way your model should move, we now must move on to get the model hooked to that root. We must do two things:

  • Unanchor the entire model, anchor the root.
    • The unanchoring helps us to move the other parts with the root. The root needs to be anchored to prevent the panel from flying about.
  • Weld the model’s parts to the root using WeldConstraints.
    • WeldConstraints are a superior option to other joints. This will be explained later.
  • Optionally, third thing, set the collision of the model to false but the root to true. Only do this if you use a root that covers the whole model and collisions with the actual model aren’t important.

To automate this process, I usually use a certain chunk of code that gets the children of the model and welds them to the root. For models that have other parts or models in them, you may want to think about GetDescendants or matching the roots of those models (PrimaryPart) to the root of the main model (tween proxy).

The following code is ran in the command bar. I like my models welded in Studio sessions as opposed to doing so in live servers, plus welding in Studio is necessary to prevent any discrepancies in running servers such as slightly dispositioned parts.

local Panel = workspace.Panel
-- Using Panel.PrimaryPart for convenience's sake
local Part1 = Panel.PrimaryPart

for _, Part0 in pairs(Panel:GetChildren()) do
	if Part0:IsA("BasePart") and not (Part0 == Part1) then
		local WeldConstraint = Instance.new("WeldConstraint")
		WeldConstraint.Part0 = Part0
		WeldConstraint.Part1 = Part1
		WeldConstraint.Parent = WeldConstraint.Part0
		
		Part0.Anchored = false
	end
end

Part1.Anchored = true
Part1.CanCollide = false

After this, we can turn on the constraint viewer to see a visual representation of what welds are doing and if we’ve got everything. A properly welded model should have everything ultimately leading up to the root and none of the welds should be drawn grey. If a weld appears grey, it’s welding two anchored parts and that needs to be corrected.

image

Let’s have a look at our welded panels.

And with this, you have finished rigging your model. There is only one more step after this and it’s to apply your tweens to the model. The fun part and what you’ve probably been waiting for.

(back to top)


Tweening Your Model

Once your model has been rigged up, you are completely set. There’s a reason I called this thread an introduction and that’s because all there is to tweening models is attaching your model’s BaseParts to a rig and moving that BasePart around. Turns out it’s not that difficult to tween models, huh?

For any kind of tweening on the platform, you are strongly encouraged to use the TweenService as tweens are handled for you on the backend and sport a sufficient amount of functionality to get you through. The only time I’d think about a custom implementation is for creating easing styles or expanding the capabilities of the TweenService.

To help you get started, I will provide two code samples available for each respective panel. The first code sample is used to rotate the panel. As far as this goes, you will want to tween the model using CFrame.Angles. Make sure your inputs are in radians.

NOTE (07/30/2021): If you’re intending to adapt this code, the one rule is that you should keep using the CFrame when attempting to tween, not the position. Welds will not update other parts when the position of your root is updated, only the CFrame.

local TweenService = game:GetService("TweenService")

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

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

local PanelSwingTween = TweenService:Create(PanelRoot, PanelSwingInfo, {
    CFrame = PanelRoot.CFrame * CFrame.Angles(0, math.rad(180), 0)
})

PanelSwingTween:Play()

And here is our result:

As for the second one, we simply need to take the logic of the first one and configure it a little. Let’s have the door move by its own size to the right, along with extra offset so it gets the door sliding into a wall feel.

local TweenService = game:GetService("TweenService")

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

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

local PanelSlideTween = TweenService:Create(PanelRoot, PanelSlideInfo, {
    CFrame = PanelRoot.CFrame * CFrame.new(PanelRoot.Size.X + 0.1, 0, 0)
})

PanelSlideTween:Play()

That code will give us this:

And with that, you are done. You now understand how to tween models, you are intrigued and you are now inclined to go tween a model. Eventually, you will have model tweens everywhere. Hahaha.

(back to top)


Addressing Potential Concerns & Practices

Now that the process has been covered, let’s look further. There is still quite a bit of information to take in. You can skip it if you aren’t interested, or stay and read for the sake of knowledge. Either way, I’d like to take some time to explain some of the thought processes behind my methods as well as other methods and address any potential concerns. I’ve had a few debates on my practices as well.

(back to top)

A Bad Legacy Method

The method I had accepted as a solution to an old thread asking how to tween models was to make a dummy CFrame object, tween that CFrame object and then call SetPrimaryPartCFrame on the model to that value every time it changed. The code for that is as follows:

local tweenService = game:GetService("TweenService")
local info = TweenInfo.new()

local function tweenModel(model, CF)
	local CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = model:GetPrimaryPartCFrame()

	CFrameValue:GetPropertyChangedSignal("Value"):connect(function()
		model:SetPrimaryPartCFrame(CFrameValue.Value)
	end)
	
	local tween = tweenService:Create(CFrameValue, info, {Value = CF})
	tween:Play()
	
	tween.Completed:connect(function()
		CFrameValue:Destroy()
	end)
end

Don’t use this code. I’m showing it to you so you can see it, but you absolutely better not do that after I took the time to explain a better method of how to tween a model.

Anyway, here are some of the issues raised with this solution:

  • The bottleneck is that ValueObject. This whole method relies on it. The moment that ValueObject goes, you have a problem on your hands.
  • You cannot use this without explicitly setting a PrimaryPart for the model. SetPrimaryPartCFrame will throw an error asking for a PrimaryPart to be set.
  • SetPrimaryPartCFrame itself is terrible. I will explain that in depth below.
  • Introduces unnecessary overhead and overcomplication to a simple problem by adding more instances and management processes to your code.

This method is still being passed around and used in some cases. Please do not accept that as a solution or good answer. You’ll find yourself battling with the code more times than you deserve to be.

(back to top)

Using SetPrimaryPartCFrame

EDIT 2021: SetPrimaryPartCFrame is getting DEPRECATED, woohoo! If you use the new Pivot API (SetPivot/GetPivot), you can absolutely rely on the old method from hereon.

If you’ve noticed, I had not used SetPrimaryPartCFrame anywhere in my code, despite this being the canonical way of addressing a model’s CFrame. In fact, using this function was one of the earliest proposals of how to tween a model. I hate this method entirely.

The problem with SetPrimaryPartCFrame is that because of the way the backend handles offset calculations from the PrimaryPart, it is capable of producing floating point errors easily. This results in your model being torn apart. The rate at which this happens is very slow, but given time and many calls, the tearing and seams in your models become visible. This is a common complaint about the use of the function and thus developers tend to stay away from it.

For those of you curious about the debacle on SetPrimaryPartCFrame, you can search up the function itself and you’ll see a lot of complaints about using the method. Here’s a thread I recommend, as it has responses from experienced developers and a former engineer:

A way to fix this issue is to handle SetPrimaryPartCFrame yourself with a custom full-Lua implementation. In this implementation, you cache the CFrames of every part except the root in a dictionary and manually offset them from the PrimaryPart when it moves. This is done by multiplying the inverse of all the part CFrames by the PrimaryPart’s CFrame. This keeps all model parts in relative space to the PrimaryPart.

local offset = primaryPart.CFrame:ToObjectSpace(boundPart)
primaryPart.CFrame = primaryPart.CFrame * CFrame.new(1, 2, 3)
boundPart.CFrame = primaryPart.CFrame:ToWorldSpace(offset)

-- You can also use CFrame inverse, which is what ToObjectSpace is internally

primaryPart.CFrame = primaryPart.CFrame * CFrame.new(1, 2, 3)
boundPart.CFrame = primaryPart.CFrame:Inverse() * boundPart.CFrame

This solution goes for those who want to anchor all the parts of their model and skip out on using a root PrimaryPart exclusively. That being said, you can still make the root of your model a visible part rather than a proxy part.

I’m not a very huge fan of this solution. I’m not a math-centric person and prefer something quick and easy to work with. As well, the user that suggested this solution to me ended up following the same paradigm as the first one with the proxy value.

(back to top)

Orientation of the Root Part

Something I stressed earlier in the tutorial under the section Setting Up the Root was that the orientation of it must be in appropriate positive coordinates. I provided both a code sample and an image to help this become more apparent.

Remember that the tweening is performed on the root. If the orientation of the root is not appropriate according to the way the model is constructed, this can cause you a bit of trouble trying to figure out which axis is the current one to turn. For example, if your top direction is facing right instead.

Always check your root’s orientation before proceeding with the rest of the tutorial. Once you make a mistake, it’s time consuming and annoying to go back over those errors and correct them.

(back to top)

Attaching Parts

This tutorial mainly states that the method we’re going to use is welding unanchored parts to an anchored root, which we tween. As you can see from the videos, this works excellently.

In order to make the parts dynamic and move relative to the root without actually performing any math operations on them, we unanchor the parts and attach them to the root with welds. This gives us the ability to control one part and by nature, control the rest.

A huge bone that was picked in this method is that it uses unanchored parts. The argument raised was that the unanchored parts were causing undue physics simulation. For a while, I didn’t have any counterexplanation and dodged answering the question until I did some investigations myself; this statement is false. And the falsity of this statement makes this method more powerful.

Unanchored parts indeed do get physically simulated, however any part welded to another is not actually physically simulated. In this scenario, the unanchored parts welded to our root are static and do not cause said undue physics simulation. The rest of the model behaves like its anchored.

You therefore don’t have to worry about any physics throttling or unintended physics issues while using this method. It is safe to your performance. :slightly_smiling_face:

(back to top)

WeldConstraints

Within this tutorial, I had mentioned that WeldConstraints are a superior option to other joint instances. I mean this very literally and the same goes for the rest of the constraints system. If you haven’t already been introduced to WeldConstraints or haven’t started using them, please do. WeldConstraints are absolutely lovely.

I have been asked in the past is if there’s any difference to using WeldConstraints and other joint instances. Application wise no but workflow wise yes. WeldConstraints have the absolute luxury of not needing to set C0/C1 - any part you connect with a WeldConstraint is welded relative in rotation and position to each other and this is done automatically.

Here is a code sample comparison when using WeldConstraints and not.

local Weld = Instance.new("Weld")
Weld.Part0 = RootPart
Weld.Part1 = ModelPart
local Offset = CFrame.new(ModelPart.Position)
Weld.C0 = RootPart.CFrame:Inverse() * Offset
Weld.C1 = ModelPart.CFrame:Inverse() * Offset
Weld.Parent = Weld.Part0

local WeldConstraint = Instance.new("WeldConstraint")
WeldConstraint.Part0 = ModelPart
WeldConstraint.Part1 = RootPart
WeldConstraint.Parent = WeldConstraint.Part0

Of course, using one or the other is completely up to you, but I would highly recommend WeldConstraints. I’ve switched most of my weld work over to WeldConstraint except in circumstances where I need another joint type. Specifically, Motor6D, for the sake of animations.

(back to top)


Conclusion

That’s all for now! Thanks for dropping by. If you have any questions, comments, concerns or other feedback to share, feel free. Let’s keep it all constructive and relevant. Happy developing!

(back to top)

659 Likes
2019 Moving Models Best Practices?
Animating Models
Is There A SetPrimaryPartCFrame Equivalent Physics Body Mover?
Simple tween script not working?
Bug or scripting error
Press E to Open Door
How to tween the Orientation of a model?
Tweening Models
Tweening Orientation using cframe
How would I use TweenService to tween the CFrame of a model?
How do i animate something like this?
Background moving train
Background moving train
CFrame furniture system
What's the smoothest way to move a model?
Scripting a wrecking ball?
CFrame Lerp issues
Moving Stage Light
Sliding door script help
How to use cframe to make object animations?
Welding issue, model gets destroyed
Help with making a door
Making a cargo caravan. Or at least a truck with tween
Moving an entire model from Point A to Point B
Any way to tween a model via TweenService?
Tween service not working properly
Need help with anchoring doors
Tween door not tweening how I want it
How do you make a wall shift out of place and move back into place?
Need help with anchoring doors
Using UserInputService to make an 'E-To-Open Door' function (All platforms supported.)
Tweening models problem
ClickDetector won't start the Tweening script
Tweening model leaves some children of the model behind
Keeping un-anchored parts on tweening objects (Cabinet style)
ClickDetector won't start the Tweening script
How do I make a Model (With a mesh) Spin?
How do I rotate an entire model?
Best way to make an oven door open?
Tweening Model But only primary part moving
Using TweenService to move whole models?
Adapting this script to use 'SetPrimaryPartCFame'
Rotating around somehting else using Tween Service
Welds not working with tween
How to move a model smoothly using cframe?
The Cars won't go straight
Any way to tween a model via TweenService?
Introducing colbert2677, Hobbyist Developer and Platform Enthusiast
How do I make a rotating door with tweens
How do I make an attachment always rotate toward the nearest waypoint?
[Totally lost] Tweening models with multiple parts
Help with tweening a model
Tweening Models
ProximityPrompt .Triggered Event Suddenly Stopped Firing
Tween not playing
How would you Tween A Model?
How would I tween an entire model to a certain position?
How to move an model
Animated Door Help!
Rotating grouped parts using script
Weld doesn't work
What would be better, Tweening or Animations for my box intro?
How to make a Sliding Door Model?
How to make a Model tween whole model?
How do i move models?
Why isn't my model tweening in my script?
How could i get this vehicle to move in a line
Door swinging not working properly, need some help with the CFrames
How do i tween a model to another part's position?
Door is not tweening
If orientation gets reset the tweened door is the wrong way, but if it the orientation is not reset it will not play the tween properly
Need help scripting a moving bus system
Making An Object In Replicated Storage Flip Upside down
Door Rotation not fast enough; for loop too slow
Is there way to rotate model with parts?
Need help with door tweening
How can I smoothly change the position of a model?
Tweening multiple parts
How do I make a sliding door?
I can't seem to resize models correctly
Error with detecting player
Help with welding a part to another part that's being tweened?
Model not rotating
How do I tween a model with two parts?
Tweening a Model Position
Model not tweening except primary part
How do I tween a model with vector3?
Proximity Part for a door
Making a NPC move in front of the player
How do I make a moving subway train?
How Do I tween a model?
Tweening models using WeldConstraints on the client doesn't seem to work
How To Tween PrimaryPartCFrames
How to tween Model:SetPrimaryPartCFrame()
Knockback Wall w/ Effect
Unsure how to use tween to rotate and how to rotate on a custom axis
Issue with moving models
How to script a background looking like it is infinitely moving while vehicle is staying still
How to create CFrame with just position, no rotation
How would I make a part spin very smoothly
Anchored BaseParts Inside Of My Model Are Offset when I Moving & Rotating Model
Tweening a group
Tweening Tree Grouped
How to tween Model:SetPrimaryPartCFrame()
Brief Introduction to Tweening Models (Obsolete)
Brief Introduction to Tweening Models (Obsolete)
How can I make a Model move using tween?
Tween Move issue
Problem with Tweening Models
Making a Tween inside of a moving Tween
Tweening with position?
How do you tween transparency, size with a model
How can I tween a modelsPrimaryPart?
Pillars won't go down
Needing help with making bed to levitate (Scripting Help)
Going about transitioning CFrame overtime
Object wont move to position with tweenservice
Need help to make a Moving Part
Tweening Problems
Tween isn't playing
Need help with tweening a door around a hinge
Can tweenservice rotate a wall on its edge without weldconstraint?
Tweening Models?
CFrame error with tweening with Unions
How can you tween or move models?
How do I move a model with Tween Service?
Why is my seat not tweening correctly?
How to make a keycard door!
Why wont this tween work?
How to make a model/part not fall (for example on the z axis) while it is unanchored
How do I make welded parts stay with an anchored part when it is moved?
Welded Parts do not move when tweening
Move and Rotate Models using Tween at the Same Time
No property named 'position' for object '...'
Tween not working for weld (URGENT HELP NEEDED)
Is Tween Function With Model:SetPrimaryPartCFrame able to make?
Welded Parts not moving
How would I make this group of parts move from its position?
Tween not working for model
How to move a model to a part's position
CFrame door has a spasm
How to get all parts to move (rotate) with all other parts in same model
How do I Tween a Model to a new Position?
How to tween a model correctly
Need help with this
(SOLVED) Prison Life Style Gate System
How to use TweenService on a model
Is there a way to make an entire model move without inserting body velocities to all descendants/parts inside
WeldConstraint not working with TweenService?
How to tween an entire model?
Is there a way to render more far away constraints physics?
TweenService moving set of parts
What are you working on currently? (2022)
MoveTo not working in LocalScript? [SOLVED]
Door Tween Not Working
How to Tween a model?
(Solved) How to Tween a Model's CFrame with :SetPrimaryPartCFrame()
Animation & Scripting Help Needed
How to Move A Model From A Proximity Prompt
Model Tweening Issue
Run Two Tweens With a Model At Once
Lua.console Progress! (Looking for command ideas)
How to set rotation of a model
How to tween a model 2023?
Rotate model of 360 degree
Help with tweening bridge segment
Code not tweening entire model even if everything set and welded correctly
Model Tweening help
How can i tween an entire model?
How to tween models?
Tweening Model, only primary part moving
I need help with model tweening!
Tweening instantly snapping to its goal position
Issues w/ Tweening the Orientation of a Model
Vector3 doesn't work with welds/Motor6Ds
How can I insert a model that attaches to a player’s UpperTorso R15?
Connecting multiple models
Model not tweening except primary part
Trouble making a Sliding Door
TweenService issue
Problem with Tweening Models
Weld Constraint not welding moving parts together properly
How do I tween a model using mouse.hit.Position and math.clamp?
Part doesn't move by using humanoid:MoveTo()
How do i rotate a model by 360 degress with tween service?
Issue with CFrames and Tweening
How come SetPrimaryPartCFrame sets the whole model CFrame with all the parts but Primarypart.CFrame in my tween doesn't?
Vector3 tween misplacing model
TweenService to rotate an object from a non-centered position
How to tween models position
How to create collection service doors?
TweenService: How does that work?
Parts don't seem to stay with the rootpart, even when welded
Question on the best way to control flying vehicles in ROBLOX
Parts don't seem to stay with the rootpart, even when welded
How would I tween the orientation of a model?
How would I tween the orientation of a model?
Obejcts won't rotate when rotating PrimaryPart
How to tween a model
My truck ramp project
How do you make a wall shift out of place and move back into place?
CFrame Door Error
Is there a way to get humanoid to move when moving a model using weld?
Y position of brick going to negative infinity when tweening cframes to look at a position
How can I smoothly rotate a model?
How would you be able to make a door system like adopt me?
Assistance with rotation and tweening
Creating tweens for multiple Gui elements
Tween multiple parts of a Model
TweenService moving part rotation issue

Very well-made, with clear thoughts and good sourcing. Can’t believe I never thought of how unreliable SetPrimaryPartCFrame could be. This is a good alternative, and I’m glad I took the time to check on it.

26 Likes

Great tutorial, will definitely be using this now. I currently use the same code you displayed in the “Bad Legacy Method”, so I’ll be sure to switch over.

9 Likes

The way I did it was tween the parts individually.

5 Likes

Not sure why you’d want to incur extra overhead and work on your behalf by tweening every part individually. The entire point of this tutorial is to demonstrate a proper way to tween models that has virtually no overhead, doesn’t require a significant amount of work and is highly viable.

I’m not too sure how this reply contributes to the topic either? I would’ve been expecting that a reply to this thread about a different method would show a better way. I don’t think it’s exactly wise to be trying to teach a method that completely counteracts the point of this tutorial.

15 Likes

The result for me for some reason gives me the object teleporting to the right instead of tweening. Have I done anything wrong? I have some grey weld lines since your script to automatically weld parts to the PrimaryPart didn’t work so I manually welded everything to the MainPart.

3 Likes

If grey weld lines are appearing (provided constraints are visualised), this means that the weld is inactive. WeldConstraints go inactive when attaching two unanchored parts. I can review the code sample again if it truly doesn’t work, it would help to have a dummy model to test that on.

As for the model teleporting around, I don’t know how to explain that behaviour. Two things that come to mind are either server lag which is causing the intermediate transitions not to show (shouldn’t be bad to the point where it’s teleporting) or your implementation, in some regard, is faulty.

Are you able to confirm that you are indeed having an error applying the way I tweened models? If so, are you able to provide either the code you’re using or a barebones file that reproduces the issue you’re experiencing using test models and code?

2 Likes

All I really did with the code was use what you provided (and changed a bit of it with the object names of course) but it would show me “PrimaryPart is not part of CT1 (the model’s name)” even though I had a PrimaryPart. The model I used has alot of parts though, that might explain the teleportation. I might try with another model that’s a simple panel like shown in the tutorial.

1 Like

It shouldn’t be teleporting around even if you have a large amount of parts involved. I’ll try and have a look at this behaviour whenever I’m able to do so, but providing me with a repro file would help me narrow down the issue even better because I can work with problem code and see where things aren’t adding up.

Thanks for letting me know. I really hope it isn’t my code that’s broken.

1 Like

(small update, i think it actually said “PrimaryPart is not part of MainPart” since i chose the mainpart, i’ve reopened studio. i’ve probably done something wrong)
ct1.rbxl (48.0 KB)

1 Like

Sorry for the late reply.

I have not been able to locate any issues within this repro, everything’s done right here. I find that it would be odd if the PrimaryPart can’t be detected. Is this relatively the same code you’re working with in your actual place? You may be referencing the wrong parent.

I’m now noticing that the error you mentioned makes me think that you were using script.Parent, which would mean that the group the code is looking at is the MainPart. PrimaryPart would neither be a property or child of MainPart.

You may want to review your code and try again to make sure that it references the right things.

1 Like

There is one big weakness with this method.
image
You wouldn’t be able to safely have explosions in your game without the risk of destroying your models.

5 Likes

It’s only a weakness if you make it one, meaning that you rely on the default behaviour of explosions (which, on activation, will break joints and apply a force to parts in range).

First and foremost, please do keep in mind that this thread is only meant to be an introduction to tweening models, not an all-purpose guide. It’s chief purpose is to lay the foundations down behind attempting to tween a model and address an old method which is bad.

From what I do know, there are a dwindling amount of games that arbitrarily allow explosion objects to use their natural effect when they are instanced. This is in favour of creating custom explosions and likewise explosion handlers. such that the explosion object is either used as a visual or not used at all.

If you need the natural explosion behaviour (which is most likely a dubious claim) and you use this method, then it will become an issue which then you need to look into changing either your explosion or method of model movement. Changing the explosion can be done by making raycast explosions (which are honestly probably better to use) or making use of an explosion’s hit event. Door movement would involve revisiting the Using SetPrimaryPartCFrame header in the tutorial and manually calculating an offset for all your parts to a certain root part to avoid the issue of models tearing apart.

8 Likes

Revisiting this tutorial after a long time for an important notice with regards to the bottom: specifically, where I note that you can also use other constraints for moving models and that a potential tutorial may be written up on that later (assuming I had the time to do so).

In short: it’s not happening.

I currently follow this tutorial myself for two of my group’s games and respectively each of them have had a glaring problem with regards to exploits based on network ownership. As a little recap, network ownership refers to the entity (the server or a client) responsible for handling the physics simulation of an unanchored assembly. My game uses constraints to move models, and it does not end well.

Please observe the following example, reported by one of said developers:

What’s going on here is: since we are using constraints, that means that we have to fully unanchor the doors and network ownership will get passed around to the nearest client meaning they’re in charge of physics simulation. With that in mind, an exploiter holding ownership can do something like this.

The obvious solution here would be to give ownership to the server and that would completely stop this exploit but at a very resource intensive cost, since clients can better simulate physics than the server can (or so that’s what I know). Other options include flagging suspicious movements on the server’s end, logging the network owner via GetNetworkOwner, kicking them and then rubberbanding the door or just making the doors client-side only. Anything where an exploiter can’t influence how doors look to others without the server’s intervention at some step of the way.

As such, due to the above concerns, I feel it’s not appropriate to write a constraints tutorial that doesn’t address exploitation and I don’t have the time to do that. Apologies. At least you’ll have this information on hand though and possibly be prepared to take measures, regardless of what you choose.

I’ll be removing the “Constraints in General” section as of this post and include a reworded version that includes an exploit advisory warning with a link to this post at a later point in time.

Cheers. Stay safe all, happy developing and good luck fighting against silly exploiters. :stuck_out_tongue_closed_eyes:

26 Likes

Sorry so to clarify, as long as you have one anchored part in the model and everything else that is welded to it is unanchored, it won’t have physics ran on it right? The exploit vulnerability only happens when you use other constraints?

1 Like

That is correct. To be able to use constraints with this tween method, all of your parts need to be anchored (including the root which you tween). Any unanchored part opens the door for physics exploits, which is what is being seen in the video.

Now on the other hand, if you follow the tutorial as shown in the original post, you should be fine. When at least one part is anchored and becomes the root of your model, network ownership doesn’t apply and thus physics exploits are mostly moot (not sure if they can detach welds and it’ll work, though from my experience this doesn’t seem to be the case). Any part welded to an anchored one will also behave as an anchored part.

So yes, you are correct. If you have at least one anchored part, physics don’t apply to the model and all parts are treated as if they’re anchored. Network ownership also isn’t applicable to anchored parts so exploiters can still fling around models but it won’t replicate. This exploit is only possible if you decide to use this tween method with constraints and unanchor everything in the model.

*Note though: WeldConstraints are the only acceptable constraints to continue to use with this method, as they are just welds that hold models together in relative space. Other constraints like PrismaticConstraint (the one used for the flinging doors in the video) are no good otherwise.

4 Likes

Can you make a model for the door?

@colbert2677 do you recommend placing the root part inside the model or outside of it?

2 Likes

@Chai_rbf Hey there, sorry for the reply. I actually do not have this model on hand, but I can upload a model that is tween-compatible for reference later if that helps.


@Planet_Dad Typically in, because the proxy part is becoming your model’s root not just for tweening but it can be the root for pretty much anything else that needs to know what the main part of a model is.

It’s generally much easier to work with that way as well. If you have some kind of wild system where a root outside works best for your use case, go for it. The welds are the key to making this work; hierarchy is irrelevant, but good to be wary of for the sake of organisation.

4 Likes

This doesnt work with very large models, it lags out studio. Any solutions?