Этот вопрос просто для того, чтобы узнать, как игра может обрабатывать столько персонажей одновременно. Я новичок в играх, поэтому прошу прощения заранее.
пример
Я создаю игру защиты башни, в которой есть 15 слотов для башен, в которых строятся башни, и каждая башня выбрасывает снаряд с определенной скоростью; скажем, каждую секунду по 2 башни создаются каждой из башен, и на поле битвы маршируют враги, скажем, 70 (каждый с 10 типами атрибутов, такими как HP, мана и т. д., которые будут меняться по мере их перемещения по поле боя).
Резюме
Башенные Count = 15
Снаряды Создано Каждая башня в секунду = 2
Общее количество ударников Created в секунду = 30
единиц в Battlefield Count = 70
Теперь, обрабатывает ли игра эти 30 снарядов и 70 единиц , обрабатывая их на 100 различных потоках (что слишком много для ПК) или 1 потоке, который перемещает их все, уменьшает их ценность и т. Д. ( Что будет довольно медленно , Я думаю)?
Я понятия не имею по этому поводу, поэтому кто-нибудь может подсказать мне, как это будет работать?
источник
Ответы:
Нет, никогда не делай этого. Никогда не создавайте новый поток для ресурса, это не масштабируется в сети, равно как и при обновлении сущностей. (Кто-нибудь помнит времена, когда у вас был один поток для чтения на сокет в Java?)
Да, для начала, это путь. «Большие двигатели» распределяют некоторую работу между потоками, но это не нужно для запуска простой игры, такой как игра в защиту башни. Вероятно, есть еще больше работы, чтобы сделать каждый тик, который вы также сделаете в этой теме. Ах да, и рендеринг конечно.
Ну ... Как вы определяете медленный ? Для 100 объектов это не должно занять больше половины миллисекунды, возможно, даже меньше, в зависимости от качества вашего кода и языка, с которым вы работаете. И даже если это занимает две полных миллисекунды, это все равно достаточно, чтобы набрать 60 т / с (тиков в секунду, в данном случае речь не идет о кадрах).
источник
Правило номер один для многопоточности: не используйте его, если вам не нужно распараллеливать на нескольких ядрах процессора для повышения производительности или скорости отклика. Требование «x и y должно происходить одновременно с точки зрения пользователя» еще не является достаточной причиной для использования многопоточности.
Зачем?
Многопоточность это сложно. Вы не можете контролировать выполнение каждого потока, что может привести к невозможности воспроизвести все виды проблем («условия гонки»). Существуют методы, позволяющие избежать этого (блокировки синхронизации, критические секции), но они имеют свои собственные проблемы («тупики»).
Обычно игры, которые имеют дело с таким небольшим количеством объектов, как несколько сотен (да, это не так уж много в разработке игр), обычно обрабатывают их последовательно, каждый логический тик, используя общую
for
цикл.Даже относительно слабые процессоры смартфонов могут выполнять миллиарды инструкций в секунду. Это означает, что даже когда логика обновления ваших объектов сложна и требует около 1000 инструкций на объект и такт, и вы стремитесь к щедрым 100 тактам в секунду, у вас достаточно процессорной мощности для десятков тысяч объектов. Да, это чрезвычайно упрощенный расчет за пределами конверта, но он дает вам представление.
Кроме того, общепринятым в разработке игр является то, что игровая логика очень редко является узким местом игры. Критически важная часть производительности - это почти всегда графика. Да, даже для 2d игр.
источник
Другие ответы были связаны с многопоточностью и мощью современных компьютеров. Чтобы ответить на более важный вопрос, то, что вы пытаетесь сделать здесь, это избегать ситуаций "n в квадрате".
Например, если у вас 1000 снарядов и 1000 врагов, наивным решением будет просто сравнить их друг с другом.
Это означает, что вы получите p * e = 1,000 * 1,000 = 1,000,000 различных чеков! Это O (n ^ 2).
С другой стороны, если вы организовываете свои данные лучше, вы можете избежать этого.
Например, если вы укажете на каждом квадрате сетки, какие враги находятся в этом квадрате, вы можете просмотреть свои 1000 снарядов и просто проверить квадрат на сетке. Теперь вам просто нужно проверить каждый снаряд по квадрату, это O (n). Вместо миллиона проверок в каждом кадре вам нужна только тысяча.
Думать об организации ваших данных и их эффективной обработке благодаря этой организации - самая большая отдельная оптимизация, которую вы можете когда-либо сделать.
источник
Не создавайте потоки для ресурса / объекта, но для раздела вашей логики программы. Например:
Преимущество этого состоит в том, что ваш графический интерфейс (например, кнопки) не обязательно застревает, если ваша логика медленная. Пользователь по-прежнему может приостановить и сохранить игру. Это также хорошо для подготовки вашей игры для мультиплеера, теперь, когда вы отделяете графику от логики.
источник
Даже Space Invaders управляли десятками взаимодействующих объектов. Принимая во внимание, что декодирование одного кадра HD H264 видео включает в себя сотни миллионов арифметических операций. У тебя есть много вычислительной мощности.
Тем не менее, вы все равно можете сделать это медленно, если вы тратите его впустую. Проблема не столько в количестве объектов, сколько в количестве выполненных испытаний на столкновение; простой подход проверки каждого объекта относительно другого объекта возводит в квадрат количество требуемых вычислений. Таким образом, тестирование 1001 объекта на столкновения потребовало бы миллиона сравнений. Часто это решается, например, не проверяя снаряды на предмет столкновения друг с другом.
источник
Я собираюсь не согласиться с некоторыми другими ответами здесь. Отдельные логические потоки являются не только хорошей идеей, но и чрезвычайно полезны для скорости обработки - если ваша логика легко разделяема .
Ваш вопрос является хорошим примером логики, которая, вероятно, отделима, если вы можете добавить к ней дополнительную логику. Например, вы можете запустить несколько потоков обнаружения попаданий, либо привязав потоки к определенным областям пространства, либо поменяв местами соответствующие объекты.
Возможно, вам НЕ нужен один поток для каждого возможного столкновения, просто потому, что это может привести к сбою планировщика; Существует также стоимость, связанная с созданием и уничтожением потоков. Лучше создать некоторое количество потоков вокруг ядер системы (или использовать метрику, подобную старой
#cores * 2 + 4
), а затем повторно использовать их после завершения процесса.Однако не вся логика легко отделима. Иногда ваши операции могут охватывать сразу все игровые данные, что делает поточную обработку бесполезной (на самом деле вредной, потому что вам нужно будет добавлять проверки, чтобы избежать проблем с потоками). Кроме того, если несколько этапов логики сильно зависят друг от друга, происходящих в определенных порядках, вам придется контролировать выполнение потоков таким образом, чтобы гарантировать, что результаты не будут зависеть от порядка. Однако эта проблема не устраняется не использованием потоков, а потоки только усугубляют ее.
Большинство игр не делают этого просто потому, что это сложнее, чем средний разработчик игр готов / может справиться с тем, что обычно не является узким местом в первую очередь. Подавляющее большинство игр ограничено GPU, а не CPU. Хотя повышение скорости процессора может помочь в целом, обычно это не главное.
При этом физические движки часто используют несколько потоков, и я могу назвать несколько игр, которые, как мне кажется, выиграли бы от нескольких логических потоков (например, игры Paradox RTS, такие как HOI3 и другие).
Я согласен с другими постами, что вам, вероятно, не нужно будет использовать темы в этом конкретном примере, даже если это может быть полезно. Потоки должны быть зарезервированы для случаев, когда у вас чрезмерная загрузка ЦП, которую нельзя оптимизировать другими способами. Это огромная задача, которая повлияет на фундаментальную конструкцию двигателя; это не то, что вы можете использовать после факта.
источник
Я думаю, что другие ответы упускают важную часть вопроса, поскольку слишком много внимания уделяют многопоточности вопроса.
Компьютер не обрабатывает сразу все объекты в игре. Он обрабатывает их в последовательности.
Компьютерная игра развивается в дискретных временных шагах. В зависимости от игры и скорости ПК эти шаги обычно составляют 30 или 60 шагов в секунду, или столько / несколько шагов, сколько может рассчитать компьютер.
На одном из таких этапов компьютер вычисляет, что будет делать каждый из игровых объектов на этом этапе, и обновляет их соответственно один за другим. Он может даже делать это параллельно, используя потоки, чтобы быть быстрее, но, как мы скоро увидим, скорость не имеет значения.
Средний процессор должен быть 2 ГГц или выше, что означает 10 9 тактов в секунду. Если мы вычислим 60 временных шагов в секунду, что листы 10 9 циклов / 60 тактов = 16666666 часов за время шага. С 70 единицами у нас все еще есть приблизительно 2 400 000 тактов на единицу, оставшуюся. Если бы нам пришлось оптимизировать, мы могли бы обновить каждый юнит всего за 240 циклов, в зависимости от сложности логики игры. Как видите, наш компьютер работает примерно в 10000 раз быстрее, чем нужно для этой задачи.
источник
Отказ от ответственности: мой самый любимый тип игр - текстовый, и я пишу это как давний программист старого MUD.
Я думаю, что важный вопрос, который вы должны задать себе, заключается в следующем: вам даже нужны темы? Я понимаю, что графическая игра, вероятно, больше использует МТ, но я думаю, что это также зависит от механики игры. (Возможно, также стоит учесть, что с графическими процессорами, процессорами и всеми другими имеющимися у нас сегодня ресурсами гораздо мощнее, что делает ваши проблемы с ресурсами столь же проблематичными, как вам может показаться; в действительности, 100 объектов практически равны нулю). Это также зависит от того, как вы определяете «все символы одновременно». Вы имеете в виду в одно и то же время? У вас этого не будет, как справедливо указывает Питер, так что все сразу не имеет значения в буквальном смысле; это только кажется таким.
Предполагая, что вы будете использовать потоки: вам определенно не следует рассматривать 100 потоков (и я даже не собираюсь вдаваться в подробности, слишком ли это много для вашего процессора или нет; я имею в виду только сложности и практичность этого).
Но помните: многопоточность не легка (как указывает Филипп) и имеет много проблем. У других гораздо больше опыта (чем у меня), чем у МТ, но я бы сказал, что они тоже предложили бы то же самое (даже если бы они были более способными, чем я, особенно без практики с моей стороны).
Некоторые утверждают, что они не согласны с тем, что потоки не выгодны, а некоторые утверждают, что каждый объект должен иметь поток. Но (и опять же, это весь текст, но даже если вы рассматриваете более одного потока, вам не нужно - и не следует - рассматривать его для каждого объекта), как указывает Филипп, игры имеют тенденцию проходить по спискам. Но все же это не только (как он предлагает, хотя я понимаю, что он реагирует только на ваши параметры стольких объектов) для стольких объектов. В MUD я программист, потому что у нас есть следующее (и это не все действия, которые происходят в режиме реального времени, так что имейте это в виду):
(Количество экземпляров, конечно, различается - все выше и ниже)
Мобильные телефоны (NPC, т.е. неигровые персонажи): 2614; прототипы: 1360 объектов: 4457; прототипов: 2281 номеров: 7983; прототипы: 7983. У каждой комнаты обычно есть свой экземпляр, но у нас также есть динамические комнаты, то есть комнаты внутри комнаты; или комнаты внутри мобильного телефона, например, живот дракона; или комнаты в объектах, например, вы вводите волшебный объект). Имейте в виду, что эти динамические комнаты существуют для каждого объекта / комнаты / мобильного телефона, который фактически определил их. Да, это очень похоже на идею World of Warcraft (я не играю в нее, но мой друг заставлял меня играть на ней, когда я какое-то время работал на машине с Windows), за исключением того, что у нас это было задолго до появления World of Warcraft.
Скрипты: 868 (в настоящее время) (как ни странно, наша команда статистики не показывает, сколько у нас прототипов, поэтому я добавлю это). Все они проводятся в областях / зонах, и у нас их 103. У нас также есть специальные процедуры, которые выполняются в разное время. У нас также есть другие события. Тогда мы также подключили розетки. Мобильные телефоны передвигаются, выполняют различные действия (помимо боя), взаимодействуют с игроками и так далее. (То же самое делают другие типы организаций).
Как мы справимся со всем этим без промедления?
сокеты: select (), очереди (вход, выход, события, другие вещи), буферы (вход, выход, другие вещи) и т. д. Они опрашиваются 10 раз в секунду.
персонажи, предметы, комнаты, бои, все: все в центральном цикле на разных импульсах.
Мы также (моя реализация, основанная на обсуждении между основателем / другим программистом и мной) провели обширное отслеживание связанного списка и проверку достоверности указателей, и у нас более чем достаточно свободных ресурсов, если мы действительно в этом нуждаемся. Все это (за исключением того, что мы расширили мир) существовало годы назад, когда было меньше оперативной памяти, мощности процессора, места на жестком диске и т. Д. И действительно, даже тогда у нас не было проблем. В описанных циклах (сценарии вызывают это так же, как и перезагрузка области / повторное заполнение, как и другие вещи), монстры, объекты (предметы) и другие вещи создаются, освобождаются и так далее. Соединения также принимаются, опрашиваются и все остальное, что вы ожидаете.
источник