Hello Devforum! I’m currently trying to make an opening/closing system for a garbage container, and I’m having a confusing issue with the tweening that’s going on with it.
A little background:
I’m trying to make it turn out something like this:
and it then ends up turning out like this:
The script:
local TS = game:GetService("TweenService")
local prox = script.Parent.Parent:WaitForChild("ProxPart"):WaitForChild("ProximityPrompt")
local Cover = script.Parent
local InvisGoal = CFrame.Angles(math.rad(45),math.rad(45),0)
local OriginalCFrame = CFrame.new(-100.795, 5.375, 149.5)
local info = TweenInfo.new(2, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
local goal = {}
goal.CFrame = InvisGoal
local BackGoal = {}
BackGoal.CFrame = OriginalCFrame
--Tweens
local OpenTween = TS:Create(Cover, info, goal)
local BackTween = TS:Create(Cover, info, BackGoal)
prox.Triggered:Connect(function()
if Cover.CFrame == OriginalCFrame then
OpenTween:Play()
else
BackTween:Play()
end
end)
I’ve never played around with CFrame.Angles before so I’m probably missing something, could anyone tell me what’s wrong and what i should change, and maybe give a little explanation on the side? Thanks!
Are the X, Y, and Z sizes the same as on the part? If you have rotated the part, the Y position could be a different side than up/down, so the script might be doing what it is supposed to, even though the Y side is changed. Check whether the Y size of the shape is the up/down side of the part, and if not, then change the part so that the Y side is rotated the correct way.
In the video, I show that even though the part has been flipped on its side, the Y size remains the same, and the side the corresponds to Y also remains the same, even though the part has been rotated onto its side.
Make sure the cover is anchored when using this script
Overview:
Create starting cframe (“OriginalCFrame”)
Goal is now just starting CFrame but turned 45 degrees on x axis. If the cover is still rotating on the wrong axis move the “math.rad(45”) to another axis on the CFrame.new
Rewrote tweenInfo to follow the format of roblox documentation cuz why not (time: number,easingStyle: Enum.EasingStyle,easingDirection: Enum.EasingDirection,repeatCount: number,reverses: bool,delayTime: number)
You already had the goals as CFrame so I don’t know why you created tables (dictionaries) for them
Everything else looked fine as far as I could tell
local TS = game:GetService("TweenService")
local prox = script.Parent.Parent:WaitForChild("ProxPart"):WaitForChild("ProximityPrompt")
local Cover = script.Parent
--[[ I'm using the cover CFrame because in the way you did it the original CFrame doesn't account for rotation (also you don't have to update the script every time you move the trash bin)]]
local OriginalCFrame = Cover.CFrame
-- Moves the original cframe 45 degrees
local Goal = OriginalCFrame * CFrame.new(math.rad(45), 0, 0)
local info = TweenInfo.new(2, Enum.EasingStyle.Back, Enum.EasingDirection.Out, 0, false, 0)
-- The goal stuff you had is unnecessary because now the goals are already cframes
--Tweens
local OpenTween = TS:Create(Cover, info, Goal)
local BackTween = TS:Create(Cover, info, OriginalCFrame)
prox.Triggered:Connect(function()
if Cover.CFrame == OriginalCFrame then
OpenTween:Play()
else
BackTween:Play()
end
end)
local TS = game:GetService("TweenService")
local prox = script.Parent.Parent:WaitForChild("ProxPart"):WaitForChild("ProximityPrompt")
local Cover = script.Parent
--[[ I'm using the cover CFrame because in the way you did it the original CFrame doesn't account for rotation (also you don't have to update the script every time you move the trash bin)]]
local OriginalCFrame = Cover.CFrame
-- Moves the original cframe 45 degrees
local Goal = OriginalCFrame * CFrame.new(math.rad(45), 0, 0)
local info = TweenInfo.new(2,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
-- The goal stuff you had is unnecessary because now the goals are already cframes
--Tweens
local OpenTween = TS:Create(Cover, info, Goal)
local BackTween = TS:Create(Cover, info, OriginalCFrame)
prox.Triggered:Connect(function()
if Cover.CFrame == OriginalCFrame then
OpenTween:Play()
else
BackTween:Play()
end
end)
You need to make an anchored hinge Part at the spot the lid needs to pivot.
Weld your unanchored door to the hinge Part.
Tween the hinge Part’s rotation, the door will follow.
There are plenty of tutorials on YouTube. For example:
You can also use the Studio Assistant (View tab > Assistant) to help you write basic scripts like this one.
Create a invisible rotation point (red cylinder, can be any shape)
Then anchor ONLY THE ROTATION POINT
Step 2
Use a rigid constraint to hold both parts together (because for whatever reason welds don’t work)
WARNING: I would recommend you put both attachments in the middle of the rotation part so the rigid constraint doesn’t combine the parts like so:
local TS = game:GetService("TweenService")
local prox = -- Add your proximity prompt here
local rotationPart = script.Parent
--[[ I'm using the rotationPart CFrame because in the way you did it the original CFrame doesn't account for rotation
(also you don't have to update the script every time you move the trash bin)]]
local OriginalCFrame = rotationPart.CFrame
-- Moves the original cframe 45 degrees
local Goal = OriginalCFrame * CFrame.Angles(math.rad(45), 0, 0)
-- EasingStyle.Back looks so cool in this situation
local info = TweenInfo.new(2,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
-- The goal stuff you had is unnecessary because now the goals are already cframes
--Tweens
-- I forgot that you had to make the properties a table
local OpenTween = TS:Create(rotationPart, info, {CFrame = Goal})
local BackTween = TS:Create(rotationPart, info, {CFrame = OriginalCFrame})
prox.Triggered:Connect(function()
if rotationPart.CFrame == OriginalCFrame then
OpenTween:Play()
else
BackTween:Play()
end
end)
“Create a script that turns the part called “Cover” 45 degrees about the part called “Rotation part” using a tween that takes 2 seconds and uses Enum.EasingStyle.Back when the proximity prompt called “ProximityPrompt” is triggered”
and it created a script that goes like this:
local TweenService = game:GetService("TweenService")
-- Find the parts in the workspace
local coverPart = workspace:FindFirstChild("Cover")
local rotationPart = workspace:FindFirstChild("Rotation part")
local proximityPrompt = workspace:FindFirstChild("ProximityPrompt", true) -- true to search all descendants
if not coverPart or not rotationPart or not proximityPrompt then
warn("Required components (Cover, Rotation part, ProximityPrompt) not found in the workspace.")
return
end
-- Function to rotate the cover part
local function rotateCover()
local pivotCFrame = rotationPart:GetPivot()
local targetCFrame = pivotCFrame * CFrame.Angles(0, math.rad(45), 0) -- Rotate 45 degrees around the Y axis
-- Define the tween information
local tweenInfo = TweenInfo.new(
2, -- Duration
Enum.EasingStyle.Back, -- Easing style
Enum.EasingDirection.Out, -- Easing direction
0, -- Times repeated
false, -- Reverses
0 -- Delay time
)
-- Create the tween
local tween = TweenService:Create(coverPart, tweenInfo, {CFrame = targetCFrame})
-- Play the tween
tween:Play()
end
-- Connect the ProximityPrompt trigger to the rotateCover function
proximityPrompt.Triggered:Connect(rotateCover)
Which I guess kinda works but has absolutely no idea what is inside the workspace (and the script is bad for performance and 10 lines longer)
As I said, it’s a guideliine.
I would have started with something simple like
‘Create a script to tween a door hinge when a ProximetyPrompt is triggered’ since you already know how to set the time, the variables, the easingstyle and other properties.
@EffBeeCee WeldConstraints work perfectly between Anchored and Unanchored Parts for tweening applications. Are you using a Weld and not setting the Part0, Part1, C0, and C1?