How to make part rotate 90 degrees a limited number of times with Tween

Hello,

So I’m making a puzzle inspired by the one in the game “The Door in the Basement” in which you have to line up some platforms rotated 90 degrees by valves in order to cross a cave. I managed to get the platforms to rotate, but there are one or two that I’d prefer to only be able to rotate a limited number of times before rotating back. Here’s 2 clips from The Door in the Basement showing this:


As you can see, they can only be rotated so many times in a certain direction. Now here’s a clip showing my game:


As you can see, the first platform in my game rotates an infinite amount of times towards the left, causing it to clip through the other rotating platforms and just makes things look messy. I’d like for it to only rotate a limited amount of times (2) in said direction before it’s able to rotate back again with the cycle continuing. Here’s the script that controls the current rotation behavior:

local info = TweenInfo.new(1.5,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut,0,false,0)
local alreadyTriggered = false
local Valve = script.Parent
local ValveClickDetector = script.Parent.ClickDetector



Valve.ClickDetector.MouseClick:Connect(function()
	if alreadyTriggered == false then
		alreadyTriggered = true

		local goals = {
			Orientation = Vector3.new(RotatingPart.Orientation.X, RotatingPart.Orientation.Y - -90, RotatingPart.Orientation.Z)
		}

		local tween = game:GetService("TweenService"):Create(RotatingPart,info,goals)

		ValveClickDetector.MaxActivationDistance = 0
		tween:Play()
		tween.Completed:Wait(1.5)
		ValveClickDetector.MaxActivationDistance = 12
		alreadyTriggered = false
	end
end)

The whole little setup just incase you wanna see it:

The model in Workspace

The part that the entire platform’s model is welded to that rotates everything

I’d truly appreciate your help as this is all left to do to be done with this entire puzzle! Hope you have a good day :slight_smile:

1 Like

You could keep track of the number of turns like this:

local info = TweenInfo.new(1.5,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut,0,false,0)
local alreadyTriggered = false
local Valve = script.Parent
local ValveClickDetector = script.Parent.ClickDetector

local turnLeft = true
local maxTurns = 2
local turnNum = 0


Valve.ClickDetector.MouseClick:Connect(function()
	if alreadyTriggered == false then
		alreadyTriggered = true
		turnNum+=1
		if turnNum==maxTurns then
			turnLeft = not turnLeft
			turnNum = 0
		end
		local goals
		if turnLeft then
			goals = {
				Orientation = Vector3.new(RotatingPart.Orientation.X, RotatingPart.Orientation.Y + 90, RotatingPart.Orientation.Z)
			}
		else
			goals = {
				Orientation = Vector3.new(RotatingPart.Orientation.X, RotatingPart.Orientation.Y - 90, RotatingPart.Orientation.Z)
			}
		end

		local tween = game:GetService("TweenService"):Create(RotatingPart,info,goals)

		ValveClickDetector.MaxActivationDistance = 0
		tween:Play()
		tween.Completed:Wait(1.5)
		ValveClickDetector.MaxActivationDistance = 12
		alreadyTriggered = false
	end
end)
2 Likes

Thanks, it works (almost). When you turn the maxTurns backwards again though and you get it back at the starting position, it moves to the right 1 time when you try turning it back around again but it then goes back to working normal towards the left if that makes sense. Why could that be?

(Btw I’ve been trying to send some clips on the problem but it keeps failing to upload for some reason)

Why are you using the Orientation property? That is a terrible approach. The property should never be edited unless you have something like an F3X-like tool.

Use CFrame instead and do CFrame = RotatingPart.CFrame * CFrame.Angles(0,math.pi,0)

The orientation part of the script was made by someone else who helped me the other day with something else, had no idea it’s a bad approach but works fine for me at the end of the day. Would you happen to know though why

?

I’m using the code that Kolvian provided now and it almost worked but the rotation acts a little off at the end:

Rotated towards the right when it’s only supposed to rotate towards the left.

Orientation is a property that resets after going above 180 degrees. If you add 90 to 180 you get 270, but orientation will go negative at that direction (for whatever reason), thus your model will be rotated incorrectly.

Alright cool cool, and what exact changes and where in the script should they be made? I tried changing it to CFrame rather than Orientation as you recommended but am struggling a tad bit with that. This is what the script looks like right now:

local info = TweenInfo.new(1.5,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut,0,false,0)
local alreadyTriggered = false
local Valve = script.Parent
local ValveClickDetector = script.Parent.ClickDetector
local RotatingPart = game.Workspace.RotatingPart1

local turnLeft = true
local maxTurns = 3
local turnNum = 0


Valve.ClickDetector.MouseClick:Connect(function()
	if alreadyTriggered == false then
		alreadyTriggered = true
		turnNum+=1
		if turnNum==maxTurns then
			turnLeft = not turnLeft
			turnNum = 0
		end
		local goals
		if turnLeft then
			goals = {
				Orientation = Vector3.new(RotatingPart.Orientation.X, RotatingPart.Orientation.Y + 90, RotatingPart.Orientation.Z)
			}
		else
			goals = {
				Orientation = Vector3.new(RotatingPart.Orientation.X, RotatingPart.Orientation.Y - 90, RotatingPart.Orientation.Z)
			}
		end

		local tween = game:GetService("TweenService"):Create(RotatingPart,info,goals)

		ValveClickDetector.MaxActivationDistance = 0
		tween:Play()
		tween.Completed:Wait(1.5)
		ValveClickDetector.MaxActivationDistance = 12
		alreadyTriggered = false
	end
end)

Replace Orientation = ... with CFrame = RotatingPart.CFrame * CFrame.Angles(0,math.pi/2,0) and make it -math.pi/2 for the other one that rotates it in the other direction.

1 Like

Awesome! Got it to work with CFrame now. It just seems to still do the weird rotating to the right 1 time at the end thing though just like in the previous footage I shared back when it still had Orientation. What do you think could be the cause this time?

local info = TweenInfo.new(1.5,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut,0,false,0)
local alreadyTriggered = false
local Valve = script.Parent
local ValveClickDetector = script.Parent.ClickDetector
local RotatingPart = game.Workspace.RotatingPart1

local turnLeft = true
local maxTurns = 3
local turnNum = 0


Valve.ClickDetector.MouseClick:Connect(function()
	if alreadyTriggered == false then
		alreadyTriggered = true
		turnNum+=1
		if turnNum==maxTurns then
			turnLeft = not turnLeft
			turnNum = 0
		end
		local goals
		if turnLeft then
			goals = {
				CFrame = RotatingPart.CFrame * CFrame.Angles(0,math.pi/2,0)
			}
		else
			goals = {
				CFrame = RotatingPart.CFrame * CFrame.Angles(0,-math.pi/2,0)
			}
		end

		local tween = game:GetService("TweenService"):Create(RotatingPart,info,goals)

		ValveClickDetector.MaxActivationDistance = 0
		tween:Play()
		tween.Completed:Wait(1.5)
		ValveClickDetector.MaxActivationDistance = 12
		alreadyTriggered = false
	end
end)

Should be working if it’s with CFrame now right?

I think you can remove this since we added CFrame.

Removed

but now it seems to go back to rotating infinitely like how the problem was from the start?

If I were to guess, something of the way the script is set up at the top could be adding additional movement towards the right side once you’ve reached the maxTurns backwards. If you notice, it doesn’t do this movement the first time you reach the maxTurns, only when you are back to the original state it was in. Do you think there’s a way for it to avoid any movement towards the other side once it’s back in it’s original state? Not sure how it would be.

Try printing turnNum when you turn it.

image

What did printing turnNum do in this?

I should have clarified. You need to print the value of turnNum:
print(turnNum)

Did so now

image

image

Sorry still a bit confused on how printing this will help fix the problem. It does print though after you turn it and the tween plays. What from here though?

I just noticed this but why do you need :Wait(1.5)? That won’t do anything.

Instead of printing that, try print(turnLeft, turnNum) and see if the results are desired.

I added a wait of 1.5 seconds in hopes that that’s the wait before the ClickDetector MaxActivationDistance = 12 again.

By results do you mean like if I’m satisfied with when it prints true and false representing how many times it rotates each direction? If so probably not so much satisfied
image

If I’m understanding right though, the number of trues and falses here represents how many rotations there are in each direction right? I’m guessing that there should only be two trues and 2 falses in a row each time as it’s supposed to only move twice only. Looks like it starts printing 3 times in a row after the first 2 trues play and I’m assuming this is where the running an extra time thing happens.

What if you try this?

local info = TweenInfo.new(1.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0)
local alreadyTriggered = false
local Valve = script.Parent
local ValveClickDetector = script.Parent.ClickDetector


local direction = 1
local maxPos = 2
local currentPos = 0
Valve.ClickDetector.MouseClick:Connect(function()
	if alreadyTriggered == false then
		alreadyTriggered = true

		local goals = {
			Orientation = RotatingPart.Orientation + Vector3.new(0, 90 * direction, 0)
		}

		local tween = game:GetService("TweenService"):Create(RotatingPart,info,goals)

		ValveClickDetector.MaxActivationDistance = 0
		tween:Play()

		-- update currentPos in direction
		currentPos += direction

		-- if currentPos has reached either end
		if currentPos == 0 or currentPos == maxPos then
		    -- invert direction
		    direction = -direction
		end

		tween.Completed:Wait()
		ValveClickDetector.MaxActivationDistance = 12
		alreadyTriggered = false
	end
end)

I’m not sure that the starting direction and pos are correct (because of the - -90), if not you’d have to change currentPos to maxPos and direction to -1.

1 Like