Странное "заикание" в box2D на разных андроид устройствах - PullRequest
4 голосов
/ 14 февраля 2012

Я разрабатываю движок и игру одновременно на C ++ и использую box2D для физики. Я тестирую на разных устройствах Android и на 2 из 3 устройств, игра работает нормально, как и физика. Тем не менее, на моей вкладке Galaxy 10.1 я время от времени испытываю что-то вроде «заикания». Вот видео на YouTube, демонстрирующее:

http://www.youtube.com/watch?v=DSbd8vX9FC0

Первое устройство, на котором запущена игра, - это Xperia Play ... второе устройство - Galaxy Tab 10.1. Нет нужды говорить, что у Galaxy Tab намного лучшее аппаратное обеспечение, чем у Xperia Play, но Box2D отстает через случайные интервалы в течение случайных отрезков времени. Код для обеих машин одинаков. Кроме того, остальная часть движка / игры на самом деле не отстает. Все время он работает со скоростью 60 кадров в секунду. Таким образом, это «заикание», похоже, представляет собой некоторую задержку или сбой при чтении значений из box2D.

Спрайты, которые вы видите движущимися, проверяют, имеют ли они прикрепленное физическое тело во время рендеринга, и устанавливают свои позиционные значения, основываясь на мировом положении физического тела. Так что, похоже, именно в этом конкретном процессе box2D, по-видимому, не синхронизирован с остальной частью приложения. Довольно странно Я понимаю, что это длинный путь, но я решил опубликовать его здесь в любом случае, чтобы посмотреть, есть ли у кого-нибудь идеи ... так как я совершенно тупой. Спасибо за любой вклад заранее!

О, П.С. Я использую фиксированный временной шаг, так как это наиболее часто рекомендуемое решение для подобных вещей. Я перешел к фиксированному временному шагу при разработке этого на своем рабочем столе, столкнулся с аналогичной проблемой, только более серьезной, и фиксированный шаг был решением. Также, как я уже говорил, игра работает стабильно на скорости 60 кадров в секунду, которая контролируется таймером с низкой задержкой, поэтому я сомневаюсь, что проблема заключается в простом лаге. Еще раз спасибо!

Ответы [ 2 ]

2 голосов
/ 15 февраля 2012

Как я уже упоминал в комментариях, это сводится к проблеме разрешения таймера.Я использовал класс таймера, который должен был получить доступ к системному таймеру с самым высоким разрешением, кроссплатформенному.Все работало отлично, за исключением того, что когда дело дошло до Android, некоторые версии работали, а некоторые версии - нет.Галактика Tab 10.1 был одним из таких случаев.

В итоге я переписал свой метод getSystemTime(), чтобы использовать новое дополнение к C ++ 11 под названием std::chrono::high_resolution_clock.Это также прекрасно работало (везде, кроме Android) ... за исключением того, что оно еще не реализовано ни в одном NDK для Android.Предполагается, что он будет реализован в 5-й версии crystax NDK R7, который на момент написания этой статьи завершен на 80%.

Я провел некоторые исследования различных методов доступа к системному времени или что-то, с помощью которых яможет основывать надежный таймер на стороне NDK, но все сводится к тому, что эти различные методы поддерживаются не на всех платформах.Я прошел через болезненный процесс написания своего собственного движка с нуля просто для того, чтобы я мог поддерживать каждую версию Android, поэтому делать ставки на непоследовательные методы бессмысленно.

Единственное разумное решениедля любого, кто сталкивается с этой проблемой, на мой взгляд, стоит просто отказаться от идеи реализации такого кода на стороне NDK .Вместо этого я собираюсь сделать это на стороне Java, поскольку до сих пор во всех моих тестах это было достаточно надежно для всех устройств, на которых я тестировал.Подробнее об этом здесь:

http://www.codeproject.com/Articles/189515/Androng-a-Pong-clone-for-Android#Gettinghigh-resolutiontimingfromAndroid7

Обновление
Теперь я реализовал предложенное мной решение, чтобы выполнить синхронизацию на стороне Java, и оно сработало.Я также обнаружил, что обработка любого относительно большого числа, независимо от типа данных (числа, такого как наносекунды от вызова монотонных часов) на стороне NDK, также приводит к серьезному отставанию в некоторых версиях Android.Поэтому я максимально оптимизировал это, передав указатель на системное время, чтобы гарантировать, что мы не передаем копию.

И последнее: мое утверждение о том, что называть монотонные часы со стороны NDK ненадежно, однако, может показаться ложным.Из доков Android на System.nanoTime () ,

... и System.nanoTime ().Эти часы гарантированно являются монотонными и являются рекомендуемой основой для определения временных интервалов общего назначения событий пользовательского интерфейса, измерений производительности и всего, что не требует измерения истекшего времени во время сна устройства.

Так что, если верить этому, может показаться, что вызов часов является надежным, но, как уже упоминалось, возникают и другие проблемы, такие как обработка выделения и сброса огромного числа, которое в результате само по себе почти урезало мою частоту кадров вдвое.Galaxy Tab 10.1 с Android 3.2. Окончательный вывод: поддержка всех устройств Android в равной степени либо чертовски близка, либо невозможна, а использование нативного кода, похоже, ухудшает ситуацию .

1 голос
/ 14 февраля 2012

Я очень новичок в разработке игр, и вы, кажется, намного опытнее, и это может быть глупо спрашивать, но вы используете delta time для обновления своего мира?Хотя вы говорите, что у вас постоянная частота кадров 60 кадров в секунду, возможно, ваш счетчик кадров вычисляет что-то неверное, и вам следует использовать delta time, чтобы пропустить некоторые кадры, когда FPS низок, или ваш мир, похоже, «отстает».Я почти уверен, что вы знакомы с этим, но я думаю, что хороший пример здесь: DeltaTimeExample хотя это реализация на языке Си.Если вам нужно, я могу вставить некоторый код из моих проектов Android о том, как я использую дельта-время, которое я разработал после этой книги: Начало игр для Android .

...