Контекст OpenGL не найден в текущем потоке

Я использую LibGDX для создания игры. Я хочу одновременно загружать / выгружать активы на лету по мере необходимости. Однако ожидание загрузки активов в основной поток вызывает задержку. Чтобы исправить это, я создал фоновый поток, который отслеживает, какие активы должны быть загружены (текстуры, звуки и т. д.) и загружает/выгружает их соответствующим образом.

к сожалению, я получаю следующую ошибку при вызове AssetManager.update() из этого потока.

com.badlogic.gdx.utils.GdxRuntimeException: java.lang.RuntimeException: No OpenGL context found in the current thread.

Я пробовал runing фоновый поток в главном потоке в начале и просто дело с первыми несколькими экранами, и все работает нормально. Я также могу изменить алгоритм, чтобы просто загрузить все в память с самого начала в том же потоке, и это тоже работает. Однако ни один из них не работает в фоновом потоке.

когда я запускаю это на Android с OpenGL ES 2.0 (который является гибким странным образом) вместо Windows, все работает нормально, и я даже могу получить размеры пикселей из изображений -но текстуры делают черный.

мои поиски сказали мне, что это проблема контекст OpenGL будучи привязанным к одному потоку, но не более того. Это объясняет, почему все работает, когда я запихиваю его в основной поток, а не когда я кладу его в другой. Как исправить эту проблему контекста?

1 ответов


во-первых, вы не должны обращаться к контексту OpenGL вне потока рендеринга.

Я предполагаю, что вы уже посмотрели на них, но просто чтобы убедиться, что прочитали статья Вики AssetManager, что немного говорит о том, как использовать AssetManager для асинхронного управления активами. В дополнение к статье wiki, проверьте AssetManagerTest чтобы лучше понять, как использовать его. Тест asset manager вероятно, ваш лучший выбор в загрузке при динамической загрузке активов.

Если вы загружаете тонну вещей, вы можете посмотреть на создание панели загрузки, чтобы загрузить что-нибудь большое заранее. Он может работать, чтобы проверить активы и такие из другого потока (и установить флаг для вызова обновления), но в конце дня вам нужно будет позвонить update () в потоке рендеринга.

имея в виду, что вам нужно вызвать update () из другого потока, я не понимаю, почему вы хотели бы, чтобы другой поток проверял условия и устанавливал флаг. Вероятно, есть больше накладных расходов, используя другой поток и синхронизируя вызов update (), чем просто делать все это в потоке рендеринга. Кроме того, метод update() приостанавливается только на пару миллисекунд одновременно, поскольку он постепенно загружает файлы. Как правило, вы просто позвоните load () для вашего актива, затем проверьте isLoaded () на ваш актив. Если он не загружен, вы вызовете update () один раз в frame until isLoaded () возвращает true. Как только он вернет true, вы можете вызвать get () и получить любой актив, который вы загружали. Все это можно сделать через основной поток рендеринга без задержки приложения во время его загрузки.

Если вы действительно хотите, чтобы ваш другой поток вызывал update (), вам нужно создать Runnable объект и вызов postRunnable() например, как они это описано в статьи на multi-продевать нитку с libGDX. Однако это побеждает весь смысл использования других потоков, потому что все, что вы используете с postRunnable, выполняется синхронно в потоке рендеринга.