# Smoothing ROBLOX Character and Vehicle Motion

When you see ROBLOX characters moving in-game, their motion occasionally appears to “stutter.” The problem is magnified in certain scenarios; for example, two characters standing in close proximity on a moving conveyor will appear to stutter dramatically in each other’s camera. ROBLOX Client Physics and Networking Lead Kevin He recently dove deep into this problem, as it applies to characters and vehicles, and has some observable improvements to share.

First off, let’s take a look at some before-and-after video. In both clips, there are three players in a vehicle and the video is captured from the camera of a non-driver passenger. On the “new” side, it’s clear that much of the vehicle’s motion stuttering has been eliminated.

If we were to watch this footage from the driver’s perspective, passenger stuttering would be reduced, too. In the rest of this article, Kevin provides the gritty technical details about how he fixed motion stuttering.

# The Problem

Motion stuttering on the surface seems like a simple problem, but it actually involves ROBLOX’s physics, networking and rendering engines — all running in 3D space. The best way to solve this sort of a widespread engineering problem is to simplify the testing environment and break the problem into manageable pieces.

First, let’s define the problem. When two characters — from here known as Player1 and Player2 — are standing in close proximity on a moving, square conveyor, they appear to stutter dramatically in each other’s cameras as they move. You can see this in the following video, which is captured from Player1′s camera. Player2 stutters, especially when viewed from an angle perpendicular to the direction of movement.

This video shows our testing environment: a bare-bones place with very few parts and a moving conveyor.

Now that we know what we’re up against, we can break motion stuttering into manageable pieces:

• Numeric errors
• Perception issue caused by camera motion
• RakNet timestamp shifting
• Interpolation Algorithm
• Interpolation Window Re-centering
• Out-of-sync rendering and physics updates

## 1. Numeric Errors

The friction force between the character and the conveyor floor is modeled as a spring connector. The spring minimizes the velocity difference between the character and the floor. Due to the nature of discrete simulation steps and numeric errors, there is always a slight vibration of the character relative to the floor. We aren’t addressing the spring connector right now, but it could be modified in the future to reduce numeric error.

## 2. Perception issue caused by camera motion

When Player1’s camera is moving along the conveyor with slight numeric error, the camera essentially vibrates. This magnifies Player2’s stuttering. Setting the camera in a fixed position helps smooth motion, but it’s not a solution, as every player generally has control of their view.

Instead of fixing the camera right now, we’ll leverage the way it magnifies stuttering as a method of verifying that we’re fixing the source of stuttering.

## 3. RakNet timestamp shifting

The first fix involves the timestamp on network packets exchanged between the server and players. Before diving in, we can use a chart to plot the trajectory of Player2 from Player1′s perspective to see where we’re starting and where we can improve.

The above chart represents Player2′s position from a stationary Player1′s perspective. For the sake of simplicity, we’re only tracking position along the X-coordinate of the conveyor (i.e., side-to-side movement); the flat, narrow peaks and valleys form due to movement across the Z-coordinate (in-and-out movement).

On the chart, the X-axis shows the passage of time and the Y-axis is the position of Player2, both as received by Player1. Look at the data points on the chart. What’s good is the slopes are relatively straight, meaning Player2 is consistently moving in the right direction on the conveyor. What’s bad is the distance between positional data – we want the spacing to be roughly even.

This piece of the problem stems from RakNet, the open-source networking library on which our networking engine is built. It attempts to compensate for differences in time, such as time zones, and network lag when creating a timestamp for each network packet traded between the server and players. This is useful, but in this application it’s undesirable, as it causes erratic distances between positional data points.

The first fix is to add a new timestamp field to our physics packets, which are independent of RakNet, absolute and without network compensation. We’ll keep the original sender timestamps to maintain the trajectory and interpolate the motion.

## 4. Bi-linear Interpolation

Interpolation is the process of inserting, estimating, or finding an intermediate term in a sequence. A good interpolation algorithm should absorb as much stuttering as possible. The following graph shows the output of ROBLOX’s existing interpolation algorithm.

Again, the X-axis shows the passage of time and the Y-axis is the position of Player2, both as received by Player1. The shape of the interpolated trajectory is not bad; however, if you look closely, you see curvatures (circled in red) that should be straight. To fix these blips in character motion trajectory, we have to work on ROBLOX’s interpolation algorithm. Currently, it’s a single-hop Lerp, or linear interpolation, which fills motion gaps by calculating the average between two data points (e.g., n and n+1).

If data points n, n+1 and n+2 have a zig-zag curvature in them due to errors, the current interpolation algorithm will spit out the exact same zig-zag curvature at high resolution. We want the interpolation algorithm to be more resilient to slight disturbances and smooth out bumps from the input trajectory.

We could do higher-order interpolation, such as cubic spline. However, those algorithms are too resource-intensive for the large-scale, multiplayer experiences of ROBLOX. Instead, we chose a simpler, bi-linear interpolation algorithm:

1. p1 = lerp(n, n+1)
2. p2 = lerp(n, n+2)
3. p3 = lerp(p1, p2)

It blends three points and is more resilient to small glitches. The following graph shows the output with bi-linear interpolation. The slope of the trajectory is straighter and free of curvature. This translates to less stuttering of Player2.

## 5. Interpolation window re-centering

ROBLOX’s interpolation algorithm uses a circular buffer that stores the five most recent data points for a part. The time between the first sample and the last sample is the optimal window — or range of time — we can use to interpolate motion for it. This window slides forward along with time and new data.

Sometimes the local rendering ticks faster (or slower) than the remote simulation. To correct that error, the current interpolation algorithm “snaps” the current sample point back to the center of the sliding window with every network frame, or about every 50 miliseconds. The distance of the snap can cause visible, periodic stuttering.

To fix this part of the motion-stuttering problem, we implemented a new version of the algorithm. It essentially snaps the current sample point back toward the center of the sliding window at a higher rate, or about every 16 miliseconds, and does so more gradually. This way, the snaps are more frequent and the error correction is spread across a greater time period. Think of it like correcting a mistake as soon as it happens, rather than letting many mistakes accumulate and eventually result in an exponentially large problem.

The effect is more evenly-spaced and higher-fidelity positional data, as you can see on the following chart.

## 6. Out-of-sync rendering and physics updates

These fixes make the stuttering of Player2 almost unnoticeable from a stationary Player1. However, there is still a high-frequency, low-amplitude stuttering when both Player1 and Player2 are moving. This is because ROBLOX’s rendering task (60Hz) runs at twice the frequency of our physics task (30Hz).

For locally simulated objects, the rendering task pulls the CFrame (coordinate frame) of parts directly from the kernel at 60Hz. Since the physics task is stepped at 30Hz, it only pulls a new position half as often. For remotely simulated objects, the rendering task pulls the CFrame of parts from the interpolator. The interpolator always outputs a new position of the part’s trajectory because it continuously performs linear interpolation. This creates relative stuttering between locally simulated parts and remotely simulated parts.

There’s a simple fix: force the network interpolator to only spit out a new part-position value if the physics “Step ID” advances. This forces the interpolator to synchronize with the physics task. In the future, when we bump physics to 240Hz, the network interpolator should automatically beef up its interpolation frequency to 240Hz. Ultimately, they’re better off synchronized.

# The Results

The results are not yet perfect. Keep in mind we are capturing the video at close distance, under the magnifier of a moving camera and from the toughest (perpendicular) angle. Character stuttering is a surprisingly complex and deep-seated issue, touching many sub-systems of our simulation engine. In the future we will continue to iterate and improve this from alternative angles.

For now, however, we will move the fixes explained in this article to ROBLOX’s production environment so you can enjoy a better gameplay experience.

## 147 thoughts on “Smoothing ROBLOX Character and Vehicle Motion”

1. Hi, My character doesn’t jump, walk or lag.
I think it is because of the change. Also the camera view is wrong.

2. Good thing you fixed that. It’s so annoying when you’re driving with someone else in the car.

3. Keep up the good work! All the time ROBLOX gets better. I may have a toast to ROBLOX & ROBLOXians, to ROBLOX!

4. i like it. recently i have noticed a lot of stuttering and it’s fixed and well rounded. thanks roblox team forever in your debt! <3

5. At last I can finally drive taxis now without the stutter. I hope this feature will fix planes as well?

6. Honestly, this is an amazing improvement, for video-makers on Roblox specifically.

However, I unfortunately run an AWESOME Computer, but it has an Intel HD Graphics card, Which is not currently compadible with Roblox’s Ambient Occlusion. It is very capable of doing so, but it does not work on it.

7. Well can you fix this bug and or glitch with cars and boats? The more players in a car/boat (maybe planes) the slower it is. Is this supposed to be here ( for real-world physics ) or is is a bug/glitch? If it is, please fix it!

8. wow roblox. i hope you keep improving little by little. ive been a member since the start, and it just keeps getting better and better. i remember the first layout. roblox 1.0 (lol i loved the little character). keep up the good work guys!

9. Just want to know, this stuttering isn’t a result of a bad wifi connection, right? Followup question, Will the “new smooth” be stuttering if I still have a bad wifi connection?

• You need a decent Wifi connection to have a quality game. This fix may reduce the stuttering caused by intermittent network connection to some extent. However it’s not meant to solve the network connectivity issue.

10. Good, now I can have effective tanks without camera glitches, now they just need to fix the camera glitch that occurs in planes that don’t use vehicle seats.

11. At last! I can never drive cars with pasengers in it becuase of that. I hope it gets fixed soon!

12. Awesome! Now can you try and fix the “All” shadows bug with the camera shadow inverting shadows?

13. I race in nascar on roblox. And when im racing i notice few cars infront of me stutter. Its annoying when you get on there bumper. and it looks like your bumper is fusing in with there bumper. Hopefully that wont happen. when its fixed.

14. Glad to see this issue is being fixed. This is going to make it a lot easier to take advantage of a moving target.

Great work Roblox, it is appreciated.

15. Finally now I can play base wars and not have to tell people I can’t let’s them ride from the lag and shuttering.

17. Would this also lead the ROBLOX team to look into the issue of vehicle lag when two players are sitting in the same car/plane. If Player1 is driving and Player2 is sitting in a passenger seat with a much slower internet connection, it seems no matter how fast Player1′s is, the entire vehicle lags.

18. Maybe why it stuttering is because the local game scripting is lagging behind all the parts that are in the place. For example, the conveyer belt script may be lagging behind the actual block of it.

19. Now I can finally fight better. Whenever I do fight I always slow down, now with the character stutter gone i can finally move without it :3

• Lol same here. So glad that it’s gone now. But, I actually haven’t noticed it in a while, so maybe it does have something to do with personal computers. I have a good computer, so if that is part of the problem, that would explain why I was getting character stutter. Vehicles were a problem though. I think.

20. Now all Roblox needs is Multiplayer Studio have fun it make take a long time e.e But seriously it could help alot.

21. Very nice!

22. oh my god yes the stuttering thing has been slowing down my character’s movement so this is great thank you!

23. Epic. Roblox does a good job with stuff like this, don’t give up just keep trying!

24. nice job guys but my laptop is still laggy and vehicle and charater motion is very difficult so keep it up we know you guys can do it!

• If your computer is laggy, then the solution is to get a new computer. ROBLOX’s physics engine is very efficient, but it cannot compensate for outdated hardware!

• My friend Braxton’s (ndarcey in ROBLOX) computer is laggy too, but not like that, no wait HIS profile does,’t work on it, mine does. It is laggy ’cause it keeps loosing connection.

25. I think it’s pretty good.