How to prevent a tweened door from breaking when spammed?

I have a door whose movement is tweened, however, if you click the door again while it’s mid tween, it’s rotation will usually mess up, making it’s resting and open rotations completely outside of their intended place.

I should clarify I want to make the door’s state capable of being changed mid-tween, instead of forcing the player to wait for it to finish opening/closing.

So far the only solution I’ve thought up is to tween by taking the doors current rotation and comparing it to it’s open/closed rotation (math.rad(rootOpenRotation.Y - doorModelRoot.Rotation.Y) (rootOpenRotation being the rotation that would be expected when the door is open ((current rotation plus 90 y), and rootStartRotation just being the rotation that it begins with) And this worked, until I rotated the door.

Upon facing any other direction this completely breaks and the door’s closed rotation is for some reason on the complete opposite side of the door.

The "working" code for the door, the door can fully open/close but interrupting the current tween will completely desync it.
local doorModel = script.Parent
local doorModelRoot = script.Parent.PrimaryPart
local clickDetector = doorModel.ClickDetector

--Variable for checking if the door is open or not
local doorOpen = false

--Gets the isTweened attribute, this WILL NOT UPDATE after the script has started.
local isTweened = script.Parent:GetAttribute("Tweened")
local openSpeed = script.Parent:GetAttribute("OpenSpeed")

--Tween info for the door.
local doorTweenInfo = TweenInfo.new(
	 openSpeed
)

--Gets the TweenService
local TweenService = game:GetService("TweenService")

--Vectors getting the start rotation of the door root, used for preventing desynchronization of the door animation.
--rootStartRotation = doorModelRoot.CFrame.Rotation
--rootOpenRotation = doorModelRoot.CFrame.Rotation + Vector3.new(0, 90, 0)





function onMouseClick()
	--Checks if door is opened or closed.
	if doorOpen == false then
		
		--Checks if the model is tweened, if it is, then it plays tweened movement, if it isn't then it instantly rotates the door.
		if isTweened then
			local OpenTween = TweenService:Create(doorModelRoot, doorTweenInfo, {CFrame = doorModelRoot.CFrame * CFrame.Angles(0, math.rad(90), 0)})
			OpenTween:Play()
			
		else
			doorModel:PivotTo(doorModelRoot:GetPivot() * CFrame.Angles(0, math.rad(90), 0))
		end
		doorOpen = true
		
	elseif doorOpen == true then
		if isTweened then
			local CloseTween = TweenService:Create(doorModelRoot, doorTweenInfo, {CFrame = doorModelRoot.CFrame * CFrame.Angles(0, math.rad(-90), 0)})
			CloseTween:Play()
		else
			doorModel:PivotTo(doorModelRoot:GetPivot() * CFrame.Angles(0, math.rad(-90), 0))
		end
		doorOpen = false
	end
end

--Connects clickDetector mouseclick to clickdetector.
clickDetector.MouseClick:Connect(onMouseClick)```

For additional information the door is operating via a root “hinge” part that the entire rest of the door is welded too.

https://i.gyazo.com/2935688e82fb5a031bb5d39f93dcec51.gif (The door functioning as intended)
https://i.gyazo.com/dbe6d6ad9b41c3cec9519e224e1422f3.gif (The problem with my current "solution)
https://i.gyazo.com/dccd69cb2cf5293c9b9cf494ff2ce567.gif (The problem I am trying to find a solution for)

1 Like

Hey!

I’ve had the same issue but I found that it is a rather simple fix…

When the tween plays, temporary disable or remove the click detector.

or something like this modified script

local opened = false

local Promt = script.Parent:WaitForChild("ProximityPrompt")

function OpenDoor()
	if opened == false then
		opened = true
		for i = 1, 21 do
			script.Parent:SetPrimaryPartCFrame(Hinge.CFrame*CFrame.Angles(0, math.rad(5), 0))
			wait()
			Promt.ActionText = "Close Door"
		end
	else
		opened = false
		for i = 1, 21 do
			script.Parent:SetPrimaryPartCFrame(Hinge.CFrame*CFrame.Angles(0, math.rad(-5), 0))
			wait()
			Promt.ActionText = "Open Door"
		end
	end
end
Promt.Triggered:Connect(function(Players)
	OpenDoor()
end)

game.ReplicatedStorage.GameEvents.CloseAllDoors.Changed:Connect(function()
	if opened == true then
		OpenDoor()
		print("Libary door 1 closed")
	else
		print("Libary door 1 already closed")
	end
end)```

ignore that last part where the replicated storage is…
that is so I can close all opened doors at once without it tweening into the wrong spot

I think the solution here is to not allow it to be spammed: add a cooldown or a debounce
Simple way to prevent people from interacting with it while its opening/closing

It might look something like this:

function foo()
if not oncooldown then
oncooldown = true
-- do stuff here
oncooldown = false
end
end
1 Like

While deboucing during the animation is probably what I’ll do, I’ll still leave this question open since it technically wasn’t answered (Figuring out a way to allow the door’s state to be changed mid-animation without breaking it)

just add a debounce variable so something like this

local Debounce = false
--in the function
if Debounce == false then
--what you want to happen
wait() --add a delay
Debounce = true
end

Instead of tweening, try using the physics engine.

Make a hinge.

Then create an invisible open/closed part that gets the orientation that you want the door to have.

Then make an AlignOrientation constraint that makes the door want to go to the orientation that the invisible part has.

I never did this myself, but there is an article on developer site that covers something along these lines:

https://developer.roblox.com/en-us/onboarding/building-a-hinged-door/1

You don’t need an AlignOrientation for a hinged door.
HingeConstraints can ActuatorType set to Servo, so you can just change the TargetAngle of the HInge to open and close the door.

1 Like

Hello, you are setting the doorOpen variable before the tween completes. Also, you should make variables for the original rotation and position for the door, so you can tween to the original CFrame once you close the door. I hope this helps you.

1 Like