When Tweening on RenderStepped there is a visible shake

I have a custom camera and I’ve always had this shake when trying to tween it every frame which I couldn’t figure out how to fix so I moved to BodyGyro and BodyPosition which was completely fine, but I’d like to re-visit tweening as it’d be cleaner since I wouldn’t need a physical part. Any ideas on how to get rid of the shake?

https://i.gyazo.com/6ed6051ce653304056cc76ea6bce4666.mp4

Here is the code:

local goal = {}
		
goal.CFrame = CFrame.new(CameraCFrame.p,CameraFocus.p)
		 
local tweenInfo = TweenInfo.new(0.5)
		 
local tween = TweenService:Create(Camera, tweenInfo, goal)
		 
tween:Play()

It looks to be more of an issue with you constantly overriding the tween. By the way the jittering happens, it looks like it’s using a different start point than what it should.

I recently made a 2D camera that used TweenService, so I know it works fine. I also think I had to modify the code a bit for when the goal of the tween has been reached, and the camera is sitting still.

I believe I did something like this (but this is probably inaccurate):

local CurrentGoal
local CurrentTween

RenderStepped:Connect(function()
    local LocalGoal = CFrame.new(CameraCFrame.p, CameraFocus.p)

    if LocalGoal ~= CurrentGoal then -- if it should make a new tween
        local Tween = TweenService:Create(Camera, Info, {CFrame = LocalGoal})
        CurrentTween = Tween
        CurrentGoal = LocalGoal

        Tween:Play()
        Tween.Completed:Connect(function()
            if CurrentTween == Tween then -- if tween is still running
                CurrentTween = nil
            end
        end)
    elseif not CurrentTween then -- if the camera isn't tweening, and there isn't a new target
        Camera.CFrame = CurrentGoal
    end
end)

This code should get rid of the shake by targeting the exact same goal and only tweening when it needs to. If you’re still having issues I’ll dig up the working version tonight when I get home :wink:

4 Likes

Nope, didn’t work :face_with_raised_eyebrow: I also tried cancelling the previous tween before starting a new one and that didn’t help either.

Don’t create and play a tween every frame. That’s not how tweens are supposed to be used.

8 Likes

So how do I do this without creating a tween every frame?

What you can do is manually interpolate the current position/rotation to the goal every frame.
Here is a crude example:

local current = camera.CFrame
local goal = CFrame.new(CameraCFrame.p,CameraFocus.p)
camera.CFrame = current:lerp(goal, 0.5)

There are better ways of doing this imo (using scripted springs) but this works well enough and simulates the same thing that springs would accomplish.

Just :lerp the CFrame every frame.

local alpha = 0.5 -- A value between 0 and 1. 1 is instantaneous. 0 doesn't move at all.
Camera.CFrame = Camera.CFrame:lerp(goal, alpha)
2 Likes

There still is a shake when lerping, much less frequent but still there…

https://i.gyazo.com/e878858e25dd3e20ef74b80b32624c35.mp4

This is a consequence of the part’s CFrame being updated before the Camera’s CFrame, and that the part’s CFrame is dependent on the Camera’s CFrame.

Make sure that the part’s CFrame is updated AFTER the Camera’s CFrame is updated.

Are you sure that the part isn’t causing the issue?

Just from looking at it, it appears the shake kinda happens consistently (starting from like 3 secs) and is more to do with the part.

What XAXA said lol.

The part is the HumanoidRootPart in the character, I’m not changing it’s CFrame.

Try this: instead of connecting the function to :RenderStepped, properly bind it to RenderStep with :BindToRenderStep. That way, you can set its priority.

I’m betting that your character updates at a RenderPriority of 300 (see Documentation - Roblox Creator Hub for more info), so the camera should update at a priority below that. (lower priority values get executed earlier)

RunService:BindToRenderStep(
    "camera"
    Enum.RenderPriority.Camera.Value,
    yourUpdateFunction -- this is the function you would normally connect to :RenderStepped
)
2 Likes

Nope, doesn’t work… Setting the render priority to Camera or lower has the same amount of shake and setting it as Character or above is even worse :face_with_raised_eyebrow:

Perhaps is because of how you’re updating the character?

EDIT: I would also want to know how and when you’re getting CameraFocus

The character is being updated by the core scripts, I haven’t changed them in any way :no_mouth:

CameraFocus is just the CFrame of the camera but 1 stud forward so I could make a CFrame with a Vector3 pos and Vector3 lookAt.

Yeah, after testing this for myself, it seems like Lerping isn’t the way to go if you want to eliminate stuttering. You may have to use springs.

EDIT: (I would also probably keep rotation (“look”) and position separate if I could. Use a spring for position, don’t use one for rotation.)

I’ve already been doing this with BodyGyro and BodyPosition for a while and it worked perfectly, but the problem with that is that you need to have a physical part. I haven’t used springs yet, do they need a physical part or do they only need an attachment?

I don’t mean SpringConstraints, I meant some sort of spring module.

I’ll admit that I barely know what I’m talking about at this point since I’ve only ever used springs for simulating gun recoil and not for camera interpolation. I really didn’t expect your problem to be harder than playing around with :lerp and RenderStepped priorities.

Nope. Springs still jitter.

Hey, I don’t know if this will help as I don’t see a loop in your code, but you don’t need to use loops with TweenService.

The number you put inside of TweenInfo.new should be how long the tween takes.

If it takes longer than that for some reason, Roblox will attempt to just teleport the object to the final position I believe.