What do you want to achieve? Keep it simple and clear!
A camera sway script that does not speed up or slow down if fps changes
What is the issue? Include screenshots / videos if possible!
I did the sway part but now im stuck trying to make the sway be the same on any framerate
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I know i have to use DeltaTime but i just dont know how to use it
I’ve been trying to find a solution for 4 hours now. Help
script:
if arms.PrimaryPart then
runService.RenderStepped:Connect(function(DeltaTime) -- sway
local Rotation = workspace.CurrentCamera.CFrame:ToObjectSpace(LastCameraCFrame)
local X,Y,Z = Rotation:ToOrientation()
SwayCFrame = SwayCFrame:Lerp(CFrame.Angles(math.sin(X) * SwayEffect, math.sin(Y) * SwayEffect, math.sin(Z) * SwayEffect), 0.1/DeltaTime/60)
LastCameraCFrame = workspace.CurrentCamera.CFrame
arms:SetPrimaryPartCFrame(cam.CFrame * SwayCFrame)
end)
end
OP is lerping, not using animations. FPS will affect the deltaTime returned by RunService events so if custom animations with CFrame are dependent on RunService then clients with a higher framerate may see unexpected results when triggering the animations (in this case, the swaying).
OP: Might want to play around with this 0.1/DeltaTime/60. Looks like you meant to write 60 * (1 > speed > 0) * DeltaTime maybe? I personally don’t know much about using deltaTime to influence speed but I do recall that use cases of it are multiplicative, not divisive.
What you want is to limit the rate, correct? Doing so is a relatively easy task if you understand the math and don’t overthink it.
The deltaTime argument that is passed to the connected function is the time that elapsed since that last RenderStep. Because this runs on the users hardware, the values this normally fluctuates between (ignoring lag) can be different for each device. However, you must keep in mind that this is not the total time passed.
What you need to do is create a variable to store the time passed and use this as measure for limiting the rate.
local TIMES_PER_FRAME = 1/20 --how often you want to update the camera every second (20 in this case)
local SWAY_SPEED = 1 --the speed you want the arms to sway at (you'll want to mess around with this)
local camera = workspace.CurrentCamera
local CurrentTime = 0 -- a local variable for storing the current elapsed time value
local LastCameraCFrame = camera.CFrame
-- other code...
if arms.PrimaryPart then
runService.RenderStepped:Connect(function(DeltaTime) -- sway
CurrentTime += DeltaTime
if CurrentTime >= TIMES_PER_FRAME then
local Rotation = camera.CFrame:ToObjectSpace(LastCameraCFrame)
LastCameraCFrame = camera.CFrame
local X,Y,Z = Rotation:ToOrientation()
SwayCFrame = SwayCFrame:Lerp(CFrame.Angles(math.sin(X) * SwayEffect, math.sin(Y) * SwayEffect, math.sin(Z) * SwayEffect), SWAY_SPEED*CurrentTime) -- I probably have the math wrong here for the lerp value; I haven't done this in awhile
arms:PivotTo(LastCameraCFrame * SwayCFrame) --replaced 'SetPrimaryPartCFrame' because it has been superseded by 'PivotTo'
CurrentTime -= TIMES_PER_FRAME --you could also use the modulus operator here, but both would achieve different results in the event of noticeable lag over a duration
end
end)
end
EDIT:
Also, just a side note in case you didn’t know, when declaring variable constants (variables that don’t change like SWAY_SPEED) the standard naming convention is to use all uppercase, as this helps separate between your constants and normal variables and makes the code slightly more readable.
The arms are now moving like this
I did change the rate to 60 after this though, but the same effect happens when i put it on 120 fps
So i changed the rate to 120 fps. I thought it was over, until the arms started moving around me like a circle
Sorry that i wasn’t clear in my question; i meant that i wanted the arms to move at the same speed in any framerate. This was the solution i came up with actually but then saw that the arms moved like this. Any advice?
Thanks for the response though, ill try to make it work in that way now
(Sorry if i’m bad at this, even though i speak english almost every day im still not good at it)
Maybe try multiplying it by the DeltaTime instead? I know that I’ve done this before, it was just so long ago that I don’t remember anymore.
Also, I just now realized my idiocy. Maybe this?
local TIMES_PER_FRAME = 1/20 --how often you want to update the camera every second (20 in this case)
local SWAY_SPEED = 1 --the speed you want the arms to sway at (you'll want to mess around with this)
local camera = workspace.CurrentCamera
local CurrentTime = 0 -- a local variable for storing the current elapsed time value
local LastCameraCFrame = camera.CFrame
-- other code...
if arms.PrimaryPart then
runService.RenderStepped:Connect(function(DeltaTime) -- sway
CurrentTime += DeltaTime
if CurrentTime >= TIMES_PER_FRAME then
CurrentTime -= TIMES_PER_FRAME --you could also use the modulus operator here, but both would achieve different results in the event of noticeable lag over a duration
local Rotation = camera.CFrame:ToObjectSpace(LastCameraCFrame)
LastCameraCFrame = camera.CFrame
local X,Y,Z = Rotation:ToOrientation()
SwayCFrame = SwayCFrame:Lerp(CFrame.Angles(math.sin(X) * SwayEffect, math.sin(Y) * SwayEffect, math.sin(Z) * SwayEffect), SWAY_SPEED*DeltaTime)
arms:PivotTo(LastCameraCFrame * SwayCFrame) --replaced 'SetPrimaryPartCFrame' because it has been superseded by 'PivotTo'
end
end)
end
If this doesn’t work please let me know. I can dig through my old projects to find the solution. Limiting the time it updates every second isn’t necessary, I just usually do that since any delay in the RenderStep can cause the rest of the loop to be delayed (especially because it’s the first).
local SwayCFrame = CFrame.new()
local camera = workspace.CurrentCamera
local LastCameraCFrame = camera.CFrame
local SWAY_SPEED = 10 --the speed you want the arms to sway at (you'll want to mess around with this)
if arms.PrimaryPart then
runService.RenderStepped:Connect(function(DeltaTime) -- sway
local Rotation = camera.CFrame:ToObjectSpace(LastCameraCFrame)
LastCameraCFrame = camera.CFrame
local X,Y,Z = Rotation:ToOrientation()
SwayCFrame = SwayCFrame:Lerp(CFrame.Angles(math.sin(X) * SwayEffect, math.sin(Y) * SwayEffect, math.sin(Z) * SwayEffect), SWAY_SPEED*DeltaTime)
arms:PivotTo(LastCameraCFrame * SwayCFrame) --replaced 'SetPrimaryPartCFrame' because it has been superseded by 'PivotTo'
end)
end