На какое-то время я испытал прерывистое «заикание» спрайтов, которые находятся в движении в моей Android-игре. Это абсолютно простая 2D игра OpenGL ES 2.0. (Это постоянная проблема, которую я неоднократно посещал).Android: Понимание OnDrawFrame, FPS и VSync (OpenGL ES 2.0)
В моем цикле игры у меня есть 2 'таймера' - тот, который будет регистрировать количество кадров в предыдущей секунде, а другой, который подсчитывает время (в миллисекундах) с конца текущей итерации onDrawFrame до начала из следующего.
Это то, что я нашел:
Когда ничего не делает, я получаю 60fps (по большей части), и каждый раз, когда onDrawFrame называется, он сообщает о себе как принимать дольше 16.667ms. Теперь, если я что-то делаю (неважно, если это 1 квад или 100 квадрациклов, результат такой же), я получаю 60 кадров в секунду (по большей части), но теперь только около 20% вызовов onDrawFrame сообщают о себе как о том, что они занимают больше времени чем 16,667 мс от последнего звонка.
Я не совсем понимаю, почему это происходит, во-первых, почему, когда onDrawFrame ничего не делает, называется ли это так «медленно» - и что более важно, почему любой вызов GL (один простой квад) сделать время между вызовами onDrawFrame дольше 16,667 мс (хотя и гораздо реже).
Я должен сказать, что когда onDrawFrame сообщает о длительности более 16,667 мс от последней итерации, он почти всегда сопровождается падением FPS (до 58 или 59), но не все время, иногда, FPS остается постоянная. И наоборот, иногда, когда FPS падает, onDrawFrame вызывается в течение 16.667 мс последнего завершения итерации.
Так ......
Я пытаюсь исправить свою игру петлю и искоренить эти «заикания» - некоторые другие вещи, чтобы отметить:
- Когда я делаю метод профилирования, он показывает glSwapBuffers, иногда занимает много времени
- Когда я делаю GL Trace, большинство сцен, которые он говорит, составляет менее 1 мс, но иногда нечетный кадр занимает 3,5-4 мс - ту же сцену. Ничего не меняется независимо от времени, которое требуется
- Почти каждый раз, когда кадр падает, или onDrawFrame сообщает о большой задержке (или и том и другом), есть визуальный глюк, но не каждый раз. Большие визуальные сбои, похоже, совпадают с несколькими «задержанными» вызовами onDrawFrame и/или отброшенными кадрами.
- Я не думаю, что это проблема сложности сцены по двум причинам: 1) даже если я снимаю свою сцену дважды, это не делает проблему хуже, я по-прежнему по большей части получаю 60FPS со случайными падение, как и раньше, и 2), даже если я снимаю сцену голыми, у меня все еще возникает проблема.
Я, очевидно, что-то недопонимаю, так что толчок в правильном направлении будет оценен.
OnDrawFrame
@Override
public void onDrawFrame(GL10 gl) {
startTime = System.nanoTime();
fps++;
totalTime = System.nanoTime() - timeSinceLastCalled;
if (totalTime > 16667000) {
Log.v("Logging","Time between onDrawFrame calls: " + (totalTime /(double)1000000));
}
//Grab time
newTime = System.currentTimeMillis() * 0.001;
frameTime = newTime - currentTime; //Time the last frame took
if (frameTime > 0.25)
frameTime = 0.25;
currentTime = newTime;
accumulator += frameTime;
while (accumulator >= dt){
saveGameState();
updateLogic();
accumulator -= dt;
}
interpolation = (float) (accumulator/dt);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
render(interpolation);
if (startTime > lastSecond + 1000000000) {
lastSecond = startTime;
Log.v("Logging","fps: "+fps);
fps=0;
}
endTime = startTime;
timeSinceLastCalled = System.nanoTime();
}
Эта петля игра выше, является одним признакам в этой превосходной article.
Являются ли сбои совпадающими с событиями сбора мусора? –
@ReubenScratton, нет, все объекты создаются спереди, в цикле нет выделений и нет GC. Кажется, это проблема синхронизации с самой игрой (я мог ошибаться, но, похоже, так). Спасибо – Zippy
Предполагая, что вы используете выделенный поток рендеринга, как вы синхронизируете состояние между ним и основным потоком? (FWIW Я никогда не использую выделенный поток рендеринга и предпочитаю быть однопоточным, но тогда я никогда не писал сложную игру) –