RenderStepped not working?

Hello, I am trying to move a part independent of the frame rate, so that the part won’t slow down with slow fps or speed up with fast fps. I am using deltaTime and Renderstepped. But, for some reason, the part is not moving and there are no errors. What could be the problem?

-- this is a localscript in the StarterPlayerScripts

local RunService = game:GetService("RunService")
local part = workspace:WaitForChild("HolePuncher2")


RunService.RenderStepped:Connect(function(deltaTime)
	for i = 0, 120, 1 do
		part.CFrame = part.CFrame + part.CFrame.RightVector * 0.25 * deltaTime

	end
	for i = 0, 120, 1 do
		part.CFrame = part.CFrame + part.CFrame.RightVector * -0.25 * deltaTime
	
	end
end)

Thanks :slight_smile:

Your code first moves the part forward 121 times and then moves it backwards 121 times by the same amount, so it ends up in the same position. And it does all this every frame. I’m not sure how your code is supposed to work, but the for loops in the renderstepped function don’t make sense.

oh, I want the part to move forward and backward 121 times but I want to have a delay so that the player can see the part moving, how would I go about doing that?

Well, you can do this:

for i = 0, 120, 1 do
	local deltatime = RunService.RenderStepped:Wait()
	part.CFrame += part.CFrame.RightVector * 0.25 * deltatime
end
for i = 0, 120, 1 do
	local deltatime = RunService.RenderStepped:Wait()
	part.CFrame += part.CFrame.RightVector * -0.25 * deltatime
end

However, although the movement speed doesn’t depend on framerate, the total movement distance will increase when framerate decreases. Why do you want it to move exactly 121 times?

The reason i want it to loop 120 times is because 0.25 * 120 = 30 studs. I just want it to move 30 studs, and this is the way I did it. Is there a better way to do this? Because I don’t want the movement distance to change.

Here’s one way.

local RunService = game:GetService("RunService")

-- 1 / 60 is the time between frames if the frame rate is 60 fps.
local MOVE_30_STUDS_TIME = 120 * 1 / 60 -- change to what you want

local part = workspace:WaitForChild("HolePuncher2")
local originalCF = part.CFrame

local startTime = os.clock()

local conn
conn = Runservice.RenderStepped:Connect(function()
	local timeSpent = os.clock() - startTime
	if timeSpent >= 2 * MOVE_30_STUDS_TIME then
		part.CFrame = originalCf
		conn:Disconnect()
	end
	elseif timeSpent < MOVE_30_STUDS_TIME then
		part.CFrame = originalCf + originalCf.RightVector * (timeSpent/MOVE_30_STUDS_TIME * 30)
	else
		part.CFrame = originalCf + originalCf.RightVector * ((2 -  timeSpent/MOVE_30_STUDS_TIME) * 30)
	end
end)

However, you could also use tweenservice. It would probably be the easiest way.

local TweenService = game:GetService("TweenService")

local MOVE_30_STUDS_TIME = 120 * 1 / 60 -- change to what you want

local part = workspace:WaitForChild("HolePuncher2")
local originalCf = part.CFrame

local tweenInfo = TweenInfo.new(MOVE_30_STUDS_TIME, Enum.EasingStyle.Linear)

local tween1 = TweenService:Create(part, tweenInfo, {CFrame = originalCf + originalCf.RightVector * 30)
local tween2 = TweenService:Create(part, tweenInfo, {CFrame = originalCf})
tween1:Play()
tween1.Completed:Wait()
tween2:Play()

Edit: I originally only set the tween time, but the easing style should also be set to linear.

1 Like

Hello! Thanks for your answer. However I don’t really understand some parts in the first code :sweat_smile:
Could you please explain this part

Is the variable timeSpent used for checking how much time is spent on moving the part?

local MOVE_30_STUDS_TIME = 120 * 1 / 60 -- couldn't you just assign 30 to this variable?
if timeSpent >= 2 * MOVE_30_STUDS_TIME then -- what is this checking for?
		part.CFrame = originalCf
		conn:Disconnect()
	end

MOVE_30_STUDS_TIME is how much time it should take for the part to move 30 studs. If you want it to take 30 seconds to move 30 studs, then you can just set MOVE_30_STUDS_TIME to 30.

Time spent is the time between when the script started running and the current time. So yes, it is the time that was spent moving the part to the location where it should be at that moment.

The code is working, but at the same time, in another localscript, I was rotating the part.

local RunService = game:GetService("RunService")
local part = workspace:WaitForChild("HolePuncher2")

while true do
	part.CFrame = part.CFrame * CFrame.fromEulerAnglesXYZ(0.2,0,0)
	RunService.Heartbeat:Wait()
end

When the part moves, it stops rotating, how would I add it to the first script

How fast do you want it to rotate? 0.2 radians per frame when framerate is 60?

Yes, normally it rotates 0.2 radians per frame when the frame rate is 60.

local RunService = game:GetService("RunService")

-- 1 / 60 is the time between frames if the frame rate is 60 fps.
local MOVE_30_STUDS_TIME = 120 * 1 / 60 -- change to what you want

local part = workspace:WaitForChild("HolePuncher2")
local originalCF = part.CFrame

local startTime = os.clock()

local conn
conn = Runservice.RenderStepped:Connect(function()
	local timeSpent = os.clock() - startTime
	if timeSpent >= 2 * MOVE_30_STUDS_TIME then
		part.CFrame = originalCf
		conn:Disconnect()
		return
	end
	local moveMul
	if timeSpent < MOVE_30_STUDS_TIME then
		moveMul =  timeSpent/MOVE_30_STUDS_TIME
	else
		moveMul = (2 -  timeSpent/MOVE_30_STUDS_TIME)
	end
	part.CFrame = originalCf * CFrame.Angles(0.2 / (1 / 60) * timeSpent, 0, 0) + originalCf.RightVector * (moveMul * 30)
end)

Does that code move and rotate at the same time, or only rotate?

It should do both. CFrame.new(originalCf.RightVector * (moveMul * 30)) is used for moving. Edit: I’m not sure if it’d have worked correctly, but I edited it and it probably works at least now.

Thank you :slight_smile: I was about to say. I will try it now

It works now.
But I tried making it loop infinetly. Like this, and It stopped working.


local RunService = game:GetService("RunService")

-- 1 / 60 is the time between frames if the frame rate is 60 fps.
local MOVE_30_STUDS_TIME = 2 -- change to what you want

local part = workspace:WaitForChild("HolePuncher2")
local originalCF = part.CFrame

local startTime = os.clock()


while true do
	local conn
	conn = RunService.RenderStepped:Connect(function()
		local timeSpent = os.clock() - startTime
		if timeSpent >= 2 * MOVE_30_STUDS_TIME then
			part.CFrame = originalCF
			conn:Disconnect()
			return
		end
		local moveMul
		if timeSpent < MOVE_30_STUDS_TIME then
			moveMul =  timeSpent/MOVE_30_STUDS_TIME
		else
			moveMul = (2 -  timeSpent/MOVE_30_STUDS_TIME)
		end
		part.CFrame = originalCF * CFrame.Angles(0.2 / (1 / 60) * timeSpent, 0, 0) + originalCF.RightVector * (moveMul * 30)
	end)
	wait()
end


local RunService = game:GetService("RunService")

-- 1 / 60 is the time between frames if the frame rate is 60 fps.
local MOVE_30_STUDS_TIME = 2 -- change to what you want
local ANGULAR_VELOCITY = 0.2 / (1 / 60)

local part = workspace:WaitForChild("HolePuncher2")
local originalCF = part.CFrame

local startTime = os.clock()
RunService.RenderStepped:Connect(function()
	local timeSpent = os.clock() - startTime
	local ful30StudsMoved = timeSpent / MOVE_30_STUDS_TIME
	local modulo2 = ful30StudsMoved % 2
	local moveMul = modulo2 <= 1 and modulo2 or (2 -  modulo2)
	part.CFrame = originalCF * CFrame.Angles(ANGULAR_VELOCITY * timeSpent, 0, 0) + originalCF.RightVector * (moveMul * 30)
end)
1 Like

This code works, but what does this line do?

local moveMul = modulo2 <= 1 and modulo2 or (2 - modulo2)

That line does pretty much the same as this

local moveMul
if modulo2 <= 1 then
	moveMul = modulo2
else
	moveMul = (2 - modulo2)
end

There are situations when an x = a and b or c doesn’t work the same way as an if statement, but that’s not a problem in this situation. It happens only when b is nil or false, and modulo2 is a number, so it can’t be nil or false. Basically this is just a shorter way to assign a value to a variable based on a condition.

The modulo operator (%) gives the remainder of division. For example, 0.45 % 2 = 0.45, 2 % 2 = 0, 2.3 % 2 = 0.3, 11.7 % 2 = 1.7. The value of modulo2 in the script is always >= 0 and < 2. If it’s between 0 and 1, the part should be moving to the right, and if its between 1 and 2, the part should be moving left.

1 Like

I think I understand now.

I tried to play it on my phone, but it kind of lags sometimes and skips some frames. Is it possible to make it smoother?

Because I saw in toh, when there are moving parts, they move at the same speed and smoothly no matter the fps.

Thanks :slight_smile: