5
\$\begingroup\$

I am working on a 3D platformer in Unity and I am targeting Android devices. The game consists of a lot of objects smoothly interpolating from the bottom of the screen to the top.

This whole time I've been testing my game at 60 fps and the performance was quite good. However, when I tested the game at 30 fps, the interpolation of the objects was no longer smooth.

I initially thought that I have way too many objects in my scene and this might be affecting the interpolating performance. So I created a new project which only has the interpolation stuff and object pooling (you can download it here). But even then, the interpolation wasn't smooth at 30 fps. Here's the code I'm using for interpolating the object:

void FixedUpdate()
{
   rb.MovePosition(transform.position + transform.up * Time.fixedDeltaTime * speed);
}

I'm using the object's Rigidbody to interpolate it. I've already set the rigidbody to "Interpolate" and I turned on "isKinematic".

I first thought that the interpolation isn't smooth since I'm using Rigidbody. So I ditched the rigidbody and used transform.Translate instead. But even then the interpolation wasn't smooth. Next I tried Vector3.Lerp. Nope. That didn't work either. The stutter was still there. I even tried Vector3.MoveTowards. That didn't work. The interpolating was still laggy. I even tried turning on GPU instancing for the objects being interpolated (since they all use the same material). That didn't do it either.

Next I started playing around with the fixed timestep (in the Time settings). I thought that maybe if I set the timestep to 0.033, then the objects will interpolate smoothly at 30 fps. But that didn't work either.

I think it's really bizarre that a simple interpolation performs so poorly at 30 fps on an Android device. If the interpolation is only for a short distance, then you don't always notice the stutter. But like I said, in my game the objects have to interpolate from the bottom of the screen all the way to the top. In this case, you can clearly see the laggy movement during interpolation.

Is it possible that long distance interpolation is simply unfeasible for Android devices at 30 fps? How do so many Android game developers manage to achieve good performance at 30 fps? Feel free to download the new project I mentioned which only has the interpolation stuff and the object pooling. It is available here. It's a very simple projects. It only has the prefab that should be interpolated, the material for the prefab, the script for interpolating the prefab, the spawning and object pooling system (for spawning the prefab), and the script for setting frame rate to 30. That's it.

Below a gif of the objects' interpolation. It's not as shaky in reality (since I had to use a bad screen recorder and compress the gif) but it's still pretty close to how the objects move at 30 fps.

non-smooth-interpolating

\$\endgroup\$
8
  • \$\begingroup\$ What do you mean that not smooth? Is it that objects move too much? Is is that you are dropping frames? Is it that you have duplicated frames? What? - a video would help. I mean of course 30 fps is not 60 fps. I am thinking that perhaps you are rendering at 60 fps but only updating at 30 fps and thus you have duplicated frames. By the way, I do not know how feasible it is in unity, but if you have the start and end positions, you could interpolate in a shader (I am thinking vertex shader unless there is something funny with the pipeline). \$\endgroup\$
    – Theraot
    Aug 5, 2019 at 15:29
  • \$\begingroup\$ Do you interpolate these objects over a big distance? Do they move from the bottom of the screen to the top over 30 frames ? Or do they include smaller animations as they are ascending ? Animating over a big distance makes it more visible that an object is "teleporting" rather than smoothly animating. \$\endgroup\$
    – TomTsagk
    Aug 5, 2019 at 16:01
  • \$\begingroup\$ @Theraot By "not smooth", I mean that there is some jitter in the objects' movement when they are interpolating from one point to another. \$\endgroup\$
    – TheSaviour
    Aug 5, 2019 at 16:05
  • \$\begingroup\$ @TomTsagk Yes I'm interpolating them over a big distance. The objects are ascending in a straight line from the bottom of the screen all the way to the top. That's when the laggy movement is most obvious. It's less obvious when I'm interpolating them over a smaller distance, but the lag is definitely still there. And no, there aren't any animations. I'm only using a script to interpolate their positions. \$\endgroup\$
    – TheSaviour
    Aug 5, 2019 at 16:10
  • 3
    \$\begingroup\$ I stepped through the frames of your .gif and notice that every 5th or 6th frame (it varies), all the platforms jump an extra step. It seems like the delta per frame is a fractional amount and the extra adds up to another step every 5th frame or so. \$\endgroup\$ Aug 6, 2019 at 4:52

2 Answers 2

0
\$\begingroup\$

There are 3 things you are possibly seeing happen (with a bonus fourth at the end)...

  1. You are not updating the screen as often as you should
  2. You are not updating the position as often as you should
  3. You are just trying to do too much at 30 FPS, and 30 FPS can't keep up.

To that end...

  1. Confirm you are really updating at 30 FPS
  2. Confirm you are really updating the position a least 30 FPS
  3. If you are doing both, then think about redesigning your game concept to slow it down

Here is one other thing to consider.

Imagine you're updating your graphics every 30 ms, and your position every 20. Frame update is on the left, position update on the right...

0 
      20    
30                  
      40
60    60            
      80
90                  
      100
120   120
      140
150
      160
180   180

You can see that sometimes you will get two moves for a frame update, which will cause a jerky motion. Despite the suggestions I have up front, I'm wondering if what you're seeing is a reflection of this kind of uneven sampling.

\$\endgroup\$
6
  • \$\begingroup\$ The uneven updates you point out are usually solved by interpolation. I think OP's question here is why isn't the built-in interpolation behaving as expected in this case. \$\endgroup\$
    – DMGregory
    Aug 5, 2019 at 23:39
  • \$\begingroup\$ Maybe because it's not doing what he thinks it's doing. And as such he's rejecting various causes. It's classic debugging 101 where you look at something and think, "But it HAS to work!" that usually means you're assuming something that's not true. \$\endgroup\$
    – Tim Holt
    Aug 5, 2019 at 23:41
  • \$\begingroup\$ Confirm you are really updating at 30 FPS: I have confirmed it by creating a UI text that displays the frame rate (which was retrieved by dividing 1 by Time.deltaTime). Confirm you are really updating the position a least 30 FPS: Now I'm not sure if I did this correctly, but in the Time settings, I set the Fixed Timestep to 0.033333. Now the object position should be updating every 30 ms. After all, the object interpolation script is in the FixedUpdate function. But just to verify, I wrote Debug.Log(Time.deltaTime) in the same FixedUpdate function and this printed 0.03 in every frame \$\endgroup\$
    – TheSaviour
    Aug 6, 2019 at 4:11
  • \$\begingroup\$ If you are doing both, then think about redesigning your game concept to slow it down: The project in which I'm testing this is already super trivial. Like I said, all it has is the object interpolation script, the object spawning script and the object pooling script, as well as the prefabs that these scripts are attached to. Nevertheless, I did break the project down earlier to remove everything but the object interpolation script and its corresponding prefab. So my project consisted of a single object interpolating from the bottom to the top. However, I still noticed the lag at 30 fps. \$\endgroup\$
    – TheSaviour
    Aug 6, 2019 at 4:14
  • \$\begingroup\$ If any of you have an android device, then I would suggest doing the following to reproduce the issue: (1) Create a cube. (2) Add a Rigidbody to the cube. Make sure it is set to Interpolate and isKinematic is true (3) Add a script to the cube and in the script, just write rb.MovePosition(transform.position + transform.up * Time.fixedDeltaTime * speed) in the FixedUpdate function. (4) Create another script and set the target frame rate to 30. (5) Attach the new script to an empty game object. (6) Go to Quality settings and make sure that the game is at the lowest quality.....(continued) \$\endgroup\$
    – TheSaviour
    Aug 6, 2019 at 4:25
0
\$\begingroup\$

I think this article summarizes the problem you are seeing FIX YOUR (UNITY) TIMESTEP!

You could calculate your fixedDeltaTime like:

Application.targetFrameRate = 30;
Time.fixedDeltaTime = 1 / Application.targetFrameRate;

Just to clear up some possible misunderstandings:

The fixed time step has nothing to do with the update or with when a current frame is drawn.

The fixed time step is only for the fixed update in which the physical calculations are performed. The fixed part is to ensure that the physical objects behave more reliably, even if you drop some frames.

Order of execution for event functions

On the other hand, there is Update, where calculations are performed, and after they are completed, no matter how long it took, the frame is finally drawn.

Also, you don't need to include the Library folder when you upload a project as it can be restored locally. I would recommend using a version control system like Git and storing projects on a server to ease collaboration. There is also a gitignore file in version control that excludes all files that do not need to be tracked (uploaded and downloaded).

For the frame stats you can use the profiler and or click the stats button on the top right of your game view window.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .