Issues with CFrame tweening and/or CFrame.Angle tweening

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!

1 Like

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.

2 Likes

One more thing, you only need one Math.Rad(45) to make it rotate, two of them causes it to rotate diagonally. Replace

local InvisGoal = 	CFrame.Angles(math.rad(45),math.rad(45),0)

with this

local InvisGoal = 	CFrame.Angles(math.rad(45),0,0)
1 Like

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)

*this is all untested so it may not work

2 Likes

There are 4 things that need to be fixed on this script, as far as I can tell:

#1
local OriginalCFrame = cover.CFrame

It is Cover, not cover, which is an easy fix, but still something that needs to be fixed.

#2
local OpenTween = TS:Create(Cover, info, goal)

It is Goal, not goal, which is, again, an easy fix, but still something that needs to be fixed.

#3
local Goal = OriginalCFrame *= CFrame.new(math.rad(45), 0, 0)

What is *=? I think it is supposed to be just *, but I could be wrong.

#4

The script gets this error when used: TweenInfo.new first argument expects a number for time.

2 Likes
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)

I’m getting this error at line 14:
image

2 Likes

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.

2 Likes

@Scottifly Very true, so…

Step 1

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:

Step 3

Add this script to the red part:

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)
Step 4

Yay you’re done

2 Likes

Studio assistant kinda sucks I used this prompt:

“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)

2 Likes

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?

2 Likes

Thanks! modified the script a little and it ended up working!

1 Like