Note: A new thread exists! Please use that one over this one!
Some context and background to understand the situation and purpose of this thread.
Nearly a year ago, I came to the DevForums to ask how to tween models. I’ve always been a fan of tweening because the fluidity and smoothness is always aesthetically attractive - I used tweens or loops anywhere I could to get that aesthetic appeal. At this point, I only knew how to do it for singular items. Models have always been troublesome for me when it came to tweens, so I posted a thread reaching for help.
Between the time I received a response and now, that thread has been linked and shared over and over, including just a few hours ago. Now the thing is, that method has been discovered as problematic. For this reason, I create this Community Tutorial on tweening models. It will provide commentary on the method and teach a better method to tweening models. This is merely scratching the surface and a starting point, there are many ways you can modify this method or take a different approach.
Yes, I see at the bottom Builder_Boy provided a response. Some people also said something similar. I’m providing a detailed version of those same responses.
So, let’s address the first thing. What is this supposed “frequently-shared” method?
The method that was marked as the solution goes as follows, in bullet points so we both can understand the workflow easily.
- A dummy object, CFrameValue, is created. This value is set to the CFrame of the model. This dummy object will act as a reference value for applying CFrames to the real object.
- The Changed signal is connected to. Every time the CFrameValue changes, the model uses SetPrimaryPartCFrame to move the model to that dummy object’s value.
- A tween is ran on the value of CFrameValue. The code above gets to work.
- The dummy object is removed when the tween finishes. Anything within the functional scope is garbage collected and we’re all good.
Code:
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
Hey though, that looks fine. What’s the issue?
Through searching and experimentation on topics unrelated to tweening, as well as a response on the thread linked in my introduction, this method actually has a few problems. These are also in bullets.
- You can’t use this code without a PrimaryPart set on the model. If you attempt to call this method without a PrimaryPart, it’ll throw an error. This will cause the rest of your script to terminate.
- SetPrimaryPartCFrame actually has float point errors. Though I myself am not sure where it comes into play, I know that the function produces these errors and enough usage of the function will slowly but surely tear your model apart.
Now, as a developer, I like neither of those things. A terminated script? A model that’s lost its original composition? We can’t be having that.
In some cases, you can modify this code to fit your needs. It’s actually a pretty good solution to get started with, but in the long run you’ll want something you can rely on at a fundamental level without the aforementioned issues. So, let’s check something new out.
What can we do to change our approach?
The new approach I applied was actually quite neat. It gets the job done, produces no errors if done right and I can litter the code anywhere I wish, the way I like to script. So, here are the steps.
- Create your model however you want. Use your existing model if you have one.
- Create an invisible part. This will act as your root.
- If you intend on tweening the entire model, have the invisible part cover the model in its exact dimensions.
- If you intend on making a pivot of sorts, make it scale up one way. Image example will be Figure 1 at the bottom of these steps.
- Weld all parts to the invisible part. Unanchor every part and set up collisions however you wish. Leave the invisible brick with anchor on and CanCollide off. You must use Motor6D.
- I use a personal mod of Ozzypig’s Weld Plugin to quickly accomplish my weld work. Instead of using ManualWelds, it’s changed to use Motor6D.
- Do your tween work on this invisible part. You’re done!
Figure 1
The neon brick is the pivot. Normally, that would be invisible and the door wouldn’t have any transparency.
In conjunction with Figure 1 (pivotal tweens), here’s some code for reference on how I make them spin open:
-- This code has been edited from its original state. This is not how I normally code.
-- I hope you're still able to follow along, despite that. Code below is an edit by Dr_K4rma.
local ts = game:GetService("TweenService")
local goal = {}
goal.CFrame = Pivot.CFrame * CFrame.Angles(0, math.rad(-90), 0) -- Pivot defined elsewhere
local tinfo = TweenInfo.new(1)
local t = ts:Create(Pivot, tinfo, goal)
t:Play()
t.Completed:Wait()
And just like that, you have yourself a tweened model. Hopefully.
One thing to keep in mind while using this method, before I close off: this method is accomplished by the use of welds. Your models are not safe and items such as explosions, if not configured correctly, can cause your model to be destroyed as explosion objects destroy joints. I recommend only using the Explosion object for effects and handling explosions another way (raycast), or by creating your own explosion aesthetics and hit effects.
Edit time! How did you mod Ozzypig’s Weld Plugin?
Glad you asked, @RuizuKun_Dev. Due to your question, I have edited the thread to direct you to the response I made on how I accomplished a mod of Ozzypig’s Weld Plugin. Now not only have you helped yourself, but you’ve helped others with the same question! Check out the response.
And I suppose we’ve got a nice little model tween tutorial.
I also have nothing else to say. Leave comments or concerns below, or something.