Camera stutters while interpolating at high velocities

GetRenderCFrame only affects parts that are replicated over the network. Regardless, that’s what we’ve been using.
The bug only affects unanchored parts.

From your initial post it looks like you are still using the RenderStepped event. I recommend trying BindToRenderStep and playing with the priority of the update.

We’ve always used BindToRenderStep with Camera priority. I just tried it at First, Last, and Last + 100 unsuccessfully.
Connecting to RenderStepped doesn’t work.

It actually reminds me of VR judder

Have a link to your game? I’m curious as to what this looks like

Does anyone know whether the physics engine uses a fixed timestep?
This looks similar to what happens when you integrate two frames if the framerate is above some target, and just one otherwise: Every other frame takes an additional step, which causes a judder similar to what we’re seeing. But it just doesn’t make sense that it would be brought out by lerp of all things.

It seems to. When Angels Fifteen experiences heavy lag, the planes fly really slowly, even though the force inputs remain the same.

Are you sure about that?

Well, yeah.
Drivers have network ownership of their cars and it does the same thing in play solo, so it’s not an issue with networking.

That article seems misleading. Unless I’m mistaken, part.CFrame will be the previous frame’s value if you use it in RenderStepped.

The cframe that gets rendered and is used in RenderStepped will always be computed in the previous frame, even if you use GetRenderCFrame.

Regardless, we use GetRenderCFrame so it’s a nonissue

Interesting.

Please include more information about the current state of this bug. A test level that contains the camera that is exhibiting the issue would dramatically increase our chances of finding and fixing this issue.

Also, for more information about reporting bugs and issues, please refer to: Steps to Report a Bug

Issue: When interpolating the camera between the current camera cframe and the cframe of a fast unanchored part, the fast part exhibits a noticeable judder. Only the fast part and parts linked to it will display any judder; the rest of the world is interpolated smoothly as expected.
This issue has been around for at least several months; probably longer.

Reproducability: Happens invariably on several windows machines with both nvidia and integrated Intel graphics chips; I haven’t tested it on other platforms. It’s agnostic to whether PGS is used, and equally affects play solo and online mode.

Repro code:
Camera.CFrame = Camera.CFrame:lerp(FastPart.CFrame, 0.5)

Repro level: JudderRepro.rbxl (408.6 KB)
Use WASDEQ to control the movement of the red cube. The judder is noticeably amplified when the part moves in a direction orthogonal to the direction of the camera.

Other stuff:
Nothing has changed since it was first reported, so @LeitrisArcade’s original bug report remains relevant.
Some ways I’ve tried and failed to mitigate this:

  • Using GetRenderCFrame
  • Messing with BindToRenderStep render priority
  • Connecting to RenderStepped
  • Connecting to Heartbeat
  • Connecting to Stepped
  • Compensating for variable step times, e.g.
    Camera.CFrame = Camera.CFrame:lerp(FastPart.CFrame, dt*nominalFramerate*0.5)
3 Likes

I’m not sure if I would expect smooth results from simply calling lerp at .5. By calling lerp at .5 statically, you’re basically saying that on every frame you want the camera to move halfway between where it is now and where you want it to be. If the part isn’t moving very fast, then these increments are small (so it would look smoother). For fast speeds, those jumps will start off very large.

2 Likes

If that were the case, then why is everything other than the target interpolating smoothly? That doesn’t make sense, for if that were the case, everything on the screen would “jutter”. Same thing happens when using cam:Interpolate(), regardless of using GetRenderCFrame or binding it to RS.

On a side note, glad this is getting some attention, thought this thread had died.

2 Likes

Because everything else is stationary. Here is the problem with your perception of the problem. When you are trying to move at the same velocity as another object, you will notice is jitter more easily than other objects because any change in perceived in the velocity of the object (increasing or decreasing) will be observable in the absolute position of the object you are chasing.

Since everything EXCEPT your target is static, even small changes in velocity won’t change the fact that these objects are moving past you.

While the static objects are moving past you at high velocities the small “jitter” on them is unnoticeable because it doesn’t change the overall motion of the terrain as you perceive it. However, because you expect the object you are chasing to stay in the same position relative to your camera you see a massive jitter because the overall perceived motion of the object is tiny.

That being said camera.CFrame = camera.CFrame:lerp(part.CFrame*camOffset, 0.5) is weird. For this to be smooth you basically have to expect that velocity stays fairly constant without much variation. You’re literally just setting the camera CFrame half way between the target position and the current camera position, expecting this result to follow the curve of the motion of the object. By expecting smooth motion you are expecting the time derivatives of the object and this goal to match up exactly. What exactly makes you think this is a reasonable assumption?

1 Like

This is still very much an issue and it makes having a camera that “lags”/falls behind a vehicle very choppy looking and it’s extremely frustrating as there is seemingly nothing we can do to prevent this behavior on our end so I definitely believe it to be a Roblox bug. I’ve tried everything that everyone has tried in this topic and more:

  • Messing with BindToRenderStep render priority
  • Connecting to RenderStepped, Heartbeat, and Stepped
  • Compensated for variable time steps (such as what @Fractality_alt tried in an earlier reply)
    Camera.CFrame = Camera.CFrame:lerp(FastPart.CFrame, dt*nominalFramerate*0.5)
  • Using TweenService instead of lerp (Although it seemed like it might have slightly reduced the stutter a bit. But that could just be the placebo effect working in my mind.)

Nothing solves the issue. I really want to have the camera fall behind my vehicle because it really makes for a cool camera effect and without it, it kills a part of it’s charm. Has anyone managed to find a way around this issue? If not then I’d really like to see some kind of action be taken on it as it’s been two years now and it’s still unresolved.

Khanovich was spot on, my code was just bad. Blindly interpolating by a fixed amount between the past state and the target state isn’t a robust way to damp motion since the camera doesn’t have a continuous concept of velocity.

The fix was to set up critically damped spring models for position and rotation.

3 Likes

It’s funny, but after watching your script, instead of interpolating the camera, my player started to rotate smoothly :sweat_smile: In particular, this is related to my script for the over-the-shoulder camera

This is still an issue. It is happening with my spaceship and it is very frustrating. I have read this entire post and none of the solutions fixed it.