My scene consists of a sphere (that is controlled by the player via touch input) and a bunch of platforms continuously moving upwards (the platforms are continuously spawned via object pooling).
At 60 fps, the movement of all the game objects is smooth. However, at 50 fps only the sphere moves smoothly, whereas the platforms have a very jerky movement.
Here’s the code I’m using to control the sphere’s movement:
Vector3 movement = new Vector3 (horizontal, 0.0f, 0.0f);
rb.AddForce(movement * speed * Time.deltaTime); //rb is the sphere's Rigidbody
And here’s the code I’m using to control the platform’s movement:
I always assumed that both Time.deltaTime and Time.fixedDeltaTime would make an object’s movement framerate independent. So why is it that the sphere’s movement is so smooth at 50 fps and the platforms’ movement is so jerky? Am I not using the MovePosition function correctly? By the way, the platforms’ rigidbodies are all set to kinematic and interpolate is enabled.
I noticed the same effect at 30 fps. Smooth sphere movement but jerky platform movement.
You can test it out by downloading the project here. It only has the platform spawning assets. It has to be tested on an Android device. You’ll notice that game platforms move smoothly at 60 fps. Anything below 60 fps leads to stutter.
I even tried keeping the platforms static and moving the camera instead. However it did not solve the problem. I can still see that the platforms are kinda jerky. I even tried abandoning Rigidbody completely and using Transform.translate to move the platforms. Still no change. I’m starting to think this isn’t a performance issue, but something else entirely. If I can’t even get this to work, then I it seems that creating any kind of infinite runner for mobile is near impossible in Unity. How on earth do games like Jetpack Joyride and Temple Run not have any lag? My project is much simpler than those games.
Is there really no other way to move a game object from one end of the screen to the other end of the screen at 30 fps without any lag? I’d really appreciate it sometime tested out my project to identify the problem because I’ve been trying to figure this out for over a year now.
This is a good bet. Make a blank project, make a single update script that moves a single object from one side to the other and back, and fiddle with the framerate and camera following until you figure out what is going wrong in the first project.
Also, some android devices have horribly inefficient network drivers, and receiving data can make the device stutter and stall, even if the data is unrelated to your application, ie, just other network traffic going to the phone OS. Does your game run better when the phone is in Airplane mode? Also, reboot the phone from scratch. Does it run better then?
That’s what I’ve been doing for a while now. The new project I’ve created has nothing but the object spawning scripts (with object pooling). The objects themselves just move from one end of the screen to the other. It’s that simple. There’s nothing else in the project. And that’s the reason I keep suggesting that people download it to see what’s wrong. You won’t have to deal with any redundant assets so it should be easy to test it out. Here’s the link again:
I played around with the Fixed Timestep (in the Time settings). I thought that maybe if I change the fixed timestep to 0.033333, then maybe the objects will move more smoothly at 30 fps. That didn’t work either.
I think I might have found the reason that a simple object moving script doesn’t perform well on my phone at 30 fps but works fine at 60 fps.
I remember a long time ago I tested my game by setting VSync count at 2. I noticed that my game actually ran at 60 fps. And when I set Vsync count to 2, my game ran at 30 fps and was laggy. Now if I’m not mistaken, if I enable Vsync, the game will ignore whatever I set as the frame rate and use the device’s refresh rate as the frame rate. This probably means that the refresh rate of my device is 60 Hz. And this leads me to speculate that the refresh rate of an Android device is also the ideal frame rate of that device. Any frame rate lower than the refresh rate will lead to poor performance.
In other words, given that the refresh rate of my Android device is 60 Hz, if I try to run a game on my device at lower than 60 fps, then the game will lag no matter what. The only way I can achieve smooth performance at 30 fps is by playing the game on a device with a refresh rate of 30 Hz.
Unfortunately, I can’t really test this theory because I only have one phone. Is there anyone who can actually verify if my speculations are correct?
You have interpolation options on the rigidbody, I’m pretty sure it’s for the visual stutter, set it to interpolate (you can try the extrapolate option but I find interpolating works better in most cases)
also, you didn’t say where this bit of logic is located, I assume it is in fixed update?
First of all, I’ve kept interpolate on this whole time. So it’s clearly not the reason for the lag.
And secondly, yes the code shown above are in FixedUpdate. You can download the project and see what’s up. It’s a fairly simple project so you shouldn’t get lost or anything.
Could anyone please give my project a try? Like I said, it’s a very simple project. All it has is the object spawning code, the object pooling code and the prefab that should be spawned. I’m sure anyone with a decent amount of android development experience should be able to identify the problem.
I’ll be quite blunt and say that I have better things to do than root through your project trying to fix a completely anectdotal Android performance problem.
Since this is your project, I urge you to rise to the challenge and keep after it, keep trying to isolate and find the problem that is causing the stutter.
Use the profiler, put in your own logging and instrumentation, get hard timing numbers at runtime on the device, bisect the project, isolate, isolate, isolate until you have the one thing that is causing the problem.
I’m sure the project has been bisected enough. The profiler doesn’t show anything out of the ordinary. The game runs at a steady 30 fps and there aren’t any weird spikes present. My issue is that a lot of developers try to aim for 30 fps on mobile and that creates the impression that 30 fps probably runs very smoothly on mobile. Yet when I set the frame rate to 30 fps, I notice some light (and some rough) stutter in the objects’ movements. Given the simplicity of my project, I doubt there’s anything wrong with any of my code or the way I’ve set up the prefabs. Because if there was something wrong, then the game wouldn’t have run so smoothly at 60 fps. And that puts me in a situation where I have to assume that when developers aim for 30 fps, they’re fully aware of the forthcoming lag and they’re fully ok with it. But that just sounds a bit absurd.
Here’s what my project looks like at 30 fps. It’s not as shaky in reality (since I had to use a bad screen recorder and compress the gif) but what you’re seeing still pretty close to how the objects move at 30 fps. This is literally all I have in my project.
Alright so I found out something interesting. I asked a friend to test out my game on his android phone. His phone uses a PowerVR GPU. And surprisingly, the game ran very smoothly on his phone even at 30 fps.
As a matter of fact, I even created a very simple project with one cube that just uses its Rigidbody to interpolate from the bottom of the screen to the top. And even that game lagged on my phone at 30 fps. (Read the next post if you want to know how I set up this project)
Hence, I’ve come to the conclusion that at 30 fps, Unity games run like garbage on phones that use the Mali gpu…or at least the Mali gpu that my phone uses (which is Mali t830 mp1).
Create another script that sets the target frame rate to 30 fps. Attach the script to an empty game object.
Set the Quality level to the lowest quality (I think it’s called “Very low”)
In “Resolution and Display” (found in Player settings), set target DPI to 240 (I usually do this for optimization purposes)
Now test the game on an Android device. When I tested it, the cube jittered during movement. What do you guys think? Is this supposed to happen? As you can tell, I haven’t done anything to the project that should make it perform so poorly. It’s just 1 cube moving across the screen. That is literally it.
And regarding Step 4, even when I use transform.Translate(Vector3.up * Time.deltaTime * speed) the cube jitters during movement. No matter what code I use to interpolate the cube, it won’t move smoothly. Do you think this is a GPU problem?
I have same issue for me it seems like RigidBody.movePosition is bounded by how far it can move in a single frame. So when there is a low frame rate, it’s not really a problem with performance, but a problem with the maximum distance Rigidbody.Move can handle in a single frame.
if I move it slower in world units, the apparent lag goes away and it behaves properly.
If I move it faster in world units (i.e. > 500 world units over 1 sec), it can’t move far enough per frame to make it there in time, so it stops somewhere along the way.