CFrame increasing unwantedly

I made a door that uses CFrame and activates when you touch a part, but everytime the door is activated, the CFrame keeps increasing.

Example of what I’m talking about.
https://streamable.com/ux5w3z

Script im using

local isopen = script.Parent.IsOpen
local idle = true

local isLeverUp = workspace.Lever.LeverScriptAirlock.isLeverUp
local ActivateCheckpoint = workspace.ActivateCheckpoint

function active(silent)
	if idle and not script.Parent.Locked then
		idle = false
		local count = 0.070
		if not isopen.Value then
			script.Parent.Parent.Door1.CanCollide = true
			script.Parent.Parent.Door2.CanCollide = true
			if not silent then
				script.Parent.Parent.Door1["Open"]:Play()
			end
			for i=1,35 do
				wait()
				script.Parent.Parent.Door1.CFrame = script.Parent.Parent.Door1.CFrame * CFrame.new(count * -1.35,0,0)
				script.Parent.Parent.Door2.CFrame = script.Parent.Parent.Door2.CFrame * CFrame.new(count * -1.35,0,0)
				if i < 18 then
					count = count * 1.05
				else
					count = count / 1.05
				end
			end
			isopen.Value = true
		wait(2)
			script.Parent.Parent.Door1.CanCollide = true
			script.Parent.Parent.Door2.CanCollide = true
			if not silent then
				script.Parent.Parent.Door1["Close"]:Play()
			end
			for i=1,35 do
				wait()
				script.Parent.Parent.Door1.CFrame = script.Parent.Parent.Door1.CFrame * CFrame.new(-count * -1.35,0,0)
				script.Parent.Parent.Door2.CFrame = script.Parent.Parent.Door2.CFrame * CFrame.new(-count * -1.35,0,0)
				if i < 18 then
					count = count * 1.05
				else
					count = count / 1.05
				end
			end
			isopen.Value = false
		end
		wait(0.5)
		idle = true
	end
end

local debounce = false

ActivateCheckpoint.Touched:Connect(function()
	if not debounce then
		debounce = true
		active()
		wait(5)
		debounce = false
	end
end)

2 Likes

You can just use tween-service, no point in creating your own loop plus it is frame-rate dependent plus it is not even the correct implementation of interpolation which is done using Lerping.

With TweenService you can also add EasingStyles to your interpolations.

1 Like

Hypothetically speaking, what if I prefer using CFrame?

For simple things like this you should be using TweenService, but if you want to know the logic behind TweenService. This is what it basically does (except the additional functions for calculating the different easing styles):

-- // Linear Interpolation \\ --

local RunService = game:GetService("RunService")

local start_cframe = workspace.PosA.CFrame
local goal_cframe = workspace.PosB.CFrame

local time_taken = 5 -- Seconds

local function interpolate(start,goal,time_taken,callback)
	local alpha = 0
	local current_time = 0
	while (alpha < 1) do
		local delta_time = RunService.Heartbeat:Wait()
		current_time += delta_time
		alpha = math.min(1, (current_time/time_taken))
		callback((start:Lerp(goal, alpha)))
	end
end

wait(5)

interpolate(
	start_cframe,
	goal_cframe,
	time_taken,
	function(current_cframe)
		workspace.Part.CFrame = current_cframe
	end
)

http://robertpenner.com/easing/

1 Like

How can I make it go back to PosA after going to PosB?

Add a wait, and swap the start and end variables.

Also, while you may not like TweenService, it’s one of the most useful services when it comes to workspace or GUI scripting.

by the time you have to do your second loop, the count variable does not return to 0.070. To fix this, simply add this after wait(2)

count = 0.070

it should look like this

			isopen.Value = true
			wait(2)
			count = 0.070
			script.Parent.Parent.Door1.CanCollide = true
			script.Parent.Parent.Door2.CanCollide = true
			if not silent then
1 Like

Call the function a second time but the start and goal swapped. If the function does not yield, edit the interpolate function and add a return true after the end of the loop.

1 Like

How can I turn this into a function? I’m using ProximityPrompt to enable functions.

interpolate(
	start_cframe,
	goal_cframe,
	time_taken,
	function(current_cframe)
		workspace.Part.CFrame = current_cframe
	end
)

Create a new function to connect it the proximity prompt, call this function inside that function:

proximity_prompt.Triggered:Connect(function(plr)
	interpolate(
		start_cframe,
		goal_cframe,
		time_taken,
		function(current_cframe)
			workspace.Part.CFrame = current_cframe
		end
	)
end)

Also why aren’t you using TweenService? They are more efficient than anything you can write in Luau, and if you think they only work for positions, you are wrong, they work for any number property. I recommend using Tweens for this, and if one tween plays while another tween is running on the same property, the old one will be canceled. I see no reason why you wouldn’t want to use Tweens for this.

How can I make the tween without any posa or posb parts? I’m trying to make a game with the least amount of parts possible.

Calculate or store CFrame variables/values.

print(workspace.PosA.CFrame)

Copy the output and put it inside a local PosA = CFrame.new(). Then you can delete the part.