Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistent jitter in iOS game

I am working on a very simple vertical scrolling game for Unity iOS. My game is experiencing inconsistent jittering. I have searched the web extensively looking for a solution without any luck. I am using Unity version 5.3.4 f1.

The Game

Gameplay screenshot

  • A character is falling down. We are using unity's character controller to move the character in Update() (Time.deltaTime is being multiplied).
  • Camera is following the character in LateUpdate() (using Vector3.Lerp() to follow).
  • Since the character is moving down, the obstacles seem to be moving upward the screen.
  • There is 1 directional light in the scene, setup for real time shadows. Shadow quality is High and Hard shadows.
  • There are no rigid bodies in the scene. And there are no major spikes in the profiler.
  • We have very simple geometry and very few draw calls/ set pass calls (avg. 7 set pass calls).
  • We have constant 60 fps.
  • Since we are running on iOS vSync is by default On and cannot be disabled.

The Problem

  • The background elements/ obstacles (Trees, rocks etc.) start jittering for no apparent reason. The behaviour is inconsistent, some times it jitters and sometimes it does not.
  • Even when it does not jitter we experience small stuttering when user gives input via touch.

What we have tried

  • We have tried all combinations of Update(), LateUpdate(), FixedUpdate(), Time.deltaTime Time.smoothDeltaTime, Lerp, reducing the scene to a few cubes and removing all colliders and triggers.
  • We have already studied the following threads: Link1, Link2, Link3 and countless other threads.
  • Initially our game was running at the default 30 fps. But after some research it seemed that our problem was due to the difference between "Frame Rate" and "Screen Refresh Rate". (to understand this issue see the following LINK). Since iOS devices have a refresh rate of 60Hz we have set our target frame rate to 60 and our game maintains a constant 60 fps.
  • After setting the target frame rate to 60 the jitter has improved but now it is inconsistent.

I am all out of ideas. Any help or pointer will be highly appreciated.

Thanks in advance.

like image 496
Anas iqbal Avatar asked Aug 03 '16 17:08

Anas iqbal


2 Answers

This could be caused by a lot of different reason, and without seeing any code I can only make a few suggestions that come to mind:

1. Float point precision error

  • Is the character constantly falling?
  • Does the error occur after the character has fallen for awhile?

That would point to a floating point precision error. instead of having the character fall, move the objects around the character from beneath screen view to above screen view so that everything occurs near the origin.

2. Instantiating often or other lag spikes

  • Are you instantiating objects or pooling them?
  • Are you performing any long calculations?
  • Do you have a lot of for/foreach/while loops?

Instantiating will cause a lag spike and create garabage that will cause the garbage collector to run more often. Since the framerate is fixed, when a slow operation occurs you'll see some jitter.

Instead of Instantiating and destorying objects when the player goes some distance, you should Instantiate a pool of GameObjects after the scene loads, make them inactive with gameObject.SetActive(false), and store them in a list, array, etc. and when you need to Instatiate a new object, simply grab one from the pool, and change it's Transform.position and gameObject.SetActive(true) when it's needed.

3. Garbage collector running often

This one is unlikely to be an issue, but still mentioning it. take this example code:

void Update()
{
    Vector3 someVector = new Vector3(0,0,0);
    float distance = someVector.magnitude;
    if (distance > 5.0f)
        Vector3 someNewVector = someVector + transform.position;
    else
        Vector3 someNewVector = Vector3.zero;
}

Everytime Update runs, it creates new variables and allocates memory for them. Next time Updateruns, it creates new variables, and allocates more memory. Eventually, the memory usage sets off the garbage collector, which goes around and frees up the memory used by all the previousUpdate` functions. Instead, you should allocate the memory at the start, and then reuse the variables.

void Start()
{
    Vector3 someVector = new Vector3(0,0,0);
    Vector3 someNewVector = new Vector3(0,0,0);
    float distance = 0f;
}
void Update()
{
    someVector = Vector3.zero;
    float distance = someVector.magnitude;
    if (distance > 5.0f)
        Vector3 someVector += transform.position;
    else
        Vector3 someVector = Vector3.zero;
}

To diagnose this, you'd need to attach the profile debugger and watch and see if the jitter is consistent with the garbage collector.

Hopefully something here might be of some help to you. Your best bet for finding the source of the jitter is to use the profiler. Here's the instructions for iOS:

Connect your iOS device to your WiFi network (local/adhoc WiFi network is used by profiler to send profiling data from device to the Unity Editor). Check “Autoconnect Profiler” checkbox in Unity’s build settings dialog. Attach your device to your Mac via cable, check the “Development Build” checkbox in Unity’s build settings dialog, and hit “Build & Run” in Unity Editor. When app launches on device open profiler window in Unity Editor (Window->Profiler).

More info: The Profiler Window

like image 120
Xander Luciano Avatar answered Sep 28 '22 05:09

Xander Luciano


Thank you all for your time.

  1. No, it is not a floating point precession error.
  2. We are instantiating objects at run-time but when the problem occurred we switched to object pooling but it didn't helped.
  3. I have done thorough profiling, even remote profiling on a device and garbage collector was also not the issue.

After further research I have come across a BLOG POST, these guys were facing almost a similar issue, and solution works in my scenario.

In short, the problem was with unity frame not syncing with device's frame drawing rate. When Unity takes a little longer to render its frame the device render loop will not wait for unity to finish and draw an empty frame which results in jitter. But, as I have said in the title of the post "Inconsistent Jitter", the blog also reports the same and so it does not happens all the time.

How do you know is it is the same problem? Well, you will see Render spikes in the profiler (although we had very minimalistic geometry). It will look more like that the Render is going mad.

Although the blog is more about Input getting laggy but It also helped in my scenario. Some might not understand how exactly to solve this issue for them I recommend this POST, which presents a much clear solution.

For further study, start reading when user named "cgJames" jumps into the CONVERSATION.

I hope this helps other as well.

like image 20
Anas iqbal Avatar answered Sep 28 '22 07:09

Anas iqbal