Каковы преимущества сопрограмм? - PullRequest
9 голосов
/ 29 августа 2011

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

Кто-нибудь хочет пролить свет на то, почему кто-то может извлечь из них пользу?

Особенно было бы неплохо получить представление о программировании игры ^^

Ответы [ 5 ]

17 голосов
/ 29 августа 2011

Хорошо, подумайте о разработке игр.

Допустим, вы делаете кат-сцену или, возможно, учебник.В любом случае, у вас есть упорядоченная последовательность команд, отправленных некоторому количеству объектов.Сущность перемещается в какое-то место, разговаривает с парнем, а затем уходит в другое место.И так далее.Некоторые команды не могут быть запущены, пока другие не закончили.

Теперь посмотрим, как работает ваша игра.Каждый кадр должен обрабатывать AI, тесты на столкновение, анимацию, рендеринг и звук, а также, возможно, другие вещи.Вы можете думать только каждый кадр.Итак, как вы помещаете такой код, где вам нужно дождаться завершения какого-либо действия, прежде чем выполнять следующее?

Если вы построите систему на C ++, у вас будет что-то, что выполнялось раньшеAI.Это будет иметь последовательность команд для обработки.Некоторые из этих команд могут быть мгновенными, например, «сообщить сущности X, чтобы они шли сюда» или «создать сущность Y здесь».Другим придется подождать, например: «Скажите объекту Z перейти сюда и больше не обрабатывать команды, пока он не перейдет сюда».Командный процессор должен вызываться каждый кадр, и он должен понимать сложные условия, такие как «объект находится в местоположении» и т. Д.

В Lua это будет выглядеть так:

local entityX = game:GetEntity("entityX");
entityX:GoToLocation(locX);
local entityY = game:SpawnEntity("entityY", locY);
local entityZ = game:GetEntity("entityZ");
entityZ:GoToLocation(locZ);
do
  coroutine.yield();
until (entityZ:isAtLocation(locZ));
return;

Для размера C ++ этот сценарий будет возобновляться один раз за кадр, пока он не будет завершен.Как только он возвращается, вы знаете, что ролик завершен, и вы можете вернуть управление пользователю.

Посмотрите, насколько проста эта логика Lua.Он делает именно то, что говорит.Это ясно, очевидно, и поэтому очень трудно ошибиться.

Сила сопрограмм заключается в возможности частично выполнить какую-то задачу, подождать, пока условие выполнится, а затем перейти к следующей задаче.

0 голосов
/ 20 марта 2013

Сопрограммы в игре: простота в использовании, легко испортить при использовании во многих местах.

Просто будьте осторожны и не используйте его во многих местах.Не делайте весь свой код AI зависимым от сопрограмм.

Подпрограммы хороши для быстрого исправления, когда вводится состояние, которого раньше не было.

Это именно то, что делает Java.Sleep () и Wait () Обе функции - лучший способ сделать невозможным отладку вашей игры.На вашем месте я бы полностью избегал любого кода, который должен использовать функцию Wait (), как это делает Coroutine.

OpenGL API - это то, на что вы должны обратить внимание.Он никогда не использует функцию wait (), но вместо этого использует чистый конечный автомат, который точно знает, в каком состоянии находится объект.Если вы используете сопрограммы, вы заканчиваете таким количеством фрагментов кода без сохранения состояния, что он наверняка будет подавляющим для отладки.

Сопрограммы хороши, когда вы создаете приложение, такое как текстовый редактор .. банковское приложение .. сервер .. база данных и т. Д. (Не игра).Плохо, когда вы делаете игру, в которой все может произойти в любой момент времени, вам нужны состояния.

Итак, на мой взгляд сопрограммы - это плохой способ программирования и оправдание для написания небольшого кода без сохранения состояния.

Но это только я.

0 голосов
/ 29 августа 2011

Множество хороших примеров для разработчиков игр.Я дам другое в пространстве расширения приложения.Рассмотрим сценарий, в котором у приложения есть механизм, который может запускать пользовательские подпрограммы в Lua, в то же время выполняя основные функции в C. Если пользователю нужно дождаться, пока механизм перейдет в определенное состояние (например, ожидание получения данных),вам либо нужно:

  • многопоточность C-программы для запуска Lua в отдельном потоке и добавления методов блокировки и синхронизации,
  • завершить подпрограмму Lua и повторить попытку с началас состоянием, переданным функции, чтобы пропустить что-либо, по крайней мере, вы перезапустите некоторый код, который должен быть запущен только один раз, или
  • выдаст подпрограмму Lua и возобновит ее, как только состояние будет достигнуто в C

Третий вариант для меня проще всего реализовать, избегая необходимости обрабатывать многопоточность на нескольких платформах.Это также позволяет коду пользователя запускаться без изменений, и выглядит так, как будто вызванная им функция заняла много времени.

0 голосов
/ 29 августа 2011

Я просто не понимаю, насколько они отличаются от функций, за исключением того, что они могут сделать паузу и позволить другому бежать на секунду.

Это довольно важное свойство. Я работал над игровым движком, который использовал их для определения времени. Например, у нас был механизм, который работал со скоростью 10 тиков в секунду, и вы могли подождать WaitTicks (x), чтобы дождаться x тиков, а на пользовательском уровне вы могли бы запустить WaitFrames (x), чтобы ждать х кадров.

Даже профессиональные нативные библиотеки параллелизма используют один и тот же тип поведения.

0 голосов
/ 29 августа 2011

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

...