Зачем разработчикам игр писать свой собственный движок вместо использования уже существующих?


41

Я заметил, что многие крупные и известные разработчики игр часто разрабатывают свои собственные движки. Примеры включают Valve, Crytek, Ubisoft, Epic Games и Square-Enix.

Может ли это быть просто потому, что они могут, или вполне вероятно, что существующие двигатели не отвечают достаточным требованиям, поэтому мы бы разработали свои собственные? Я с трудом представляю себе игру, которая требует определенного движка. Подобных Unity или Unreal достаточно просто, чтобы сделать любую игру; даже если нет, у них есть исходный код, который можно изменить, чтобы удовлетворить даже некоторые экстраординарные потребности.

Зачем разработчикам игр писать свой собственный движок вместо использования уже существующих?


1
Возможный дубликат: gamedev.stackexchange.com/questions/12488/… и связанный с ним: gamedev.stackexchange.com/questions/859/…
MichaelHouse

1
Они не хотят лицензировать игровые движки других компаний и платить им.
Янош Турански

Я думаю, это то, что вы делаете, когда вокруг вас работают сотрудники 9K + ...
гламперт

3
Есть несколько контрпримеров больших студий, которые создают названия AAA, используя сторонние движки, такие как Unreal или CryEngine .
Филипп

3
Valve начали использовать движок Quake, а затем написали свои собственные для более поздних игр. Часто нужно научиться использовать то, что доступно, а затем в конечном итоге захотеть достичь чего-то большего, чем предлагает существующий движок. В этот момент вы должны сделать тяжелые модификации или свернуть свои собственные.
Nairou

Ответы:


53

Существует несколько причин, по которым студия может «строить» вместо «покупать» свои технологии:

  • Устаревшие технологии; студия, возможно, начала создавать свой собственный набор инструментов до того, как для него существовало жизнеспособное промежуточное программное обеспечение.
  • Особые требования; студия может иметь определенный набор требований, который не очень подходит для существующего промежуточного программного обеспечения или
  • Бюджетные проблемы; студия может быть не в состоянии оплатить расходы или договорные обязательства существующего промежуточного программного обеспечения.
  • «Не построенный здесь синдром»; Техническое руководство студий может быть осторожным (разумно или неоправданно) в отношении технологии, которую они не создавали, и поэтому не до конца понимают.

В целом, имеет смысл владеть и контролировать вещи, которые имеют решающее значение для успеха вашего бизнеса, и отдавать на аутсорсинг те, которые не являются таковыми.

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

Для других технология может быть основой успеха. Например, студии, которые создают MMO, обычно должны сами создавать эту инфраструктуру, потому что это имеет решающее значение для их успеха (а существующее промежуточное программное обеспечение, как правило, не подходит, по крайней мере для более крупных «AAA» -типов).

Обратите внимание, что некоторые из перечисленных вами студий (в частности, Crytek и Epic) перестали пытаться доминировать непосредственно на игровом рынке и почти наверняка сделали гораздо больше в качестве поставщиков промежуточного программного обеспечения, чем разработчиков игр.


20
Я бы добавил, что иногда есть технологии, которые «строятся здесь». Одним из примеров является то, как Unity3D меняет свои EULA для каждой версии и добавляет странные ограничения, такие как отсутствие «азартных игр». Когда вы лицензируете технику, вы зависите от лицензиара, чтобы не отворачиваться и не отзывать лицензию без особой причины (например, с правами ИС на создание лицензированных игр) или решаете поручить вам исправить их ошибки.
Скрылар

серьезно, Unity говорит "нет азартных игр"? У них даже была специальная страница об азартных играх в разделе «Сообщество» на их веб-сайте!
jhocking

На странице Unity здесь unity3d.com/industries/gambling говорит, что вы можете купить «лицензию Unity Gambling». Я не нашел цену за это, но похоже, что они все еще позволяют вам делать игры для азартных игр, если вы платите за специальное лицензирование.
Алекс

1
Кроме того, легче начать с того, что вы уже знаете, и в конечном итоге создать двигатель, даже не зная, что такое двигатель. Движок - это не что иное, как набор вариантов использования; если вы пытаетесь уменьшить избыточность, вы в конечном итоге пишете движок, а если вы пытаетесь просто построить игру, вы в конечном итоге получаете монолитную систему. Очень трудно получить игровой движок и научиться отображать пиксель, а затем понять, что он не может этого сделать, потому что он видит все как текстуру. Вам не нужно иметь дело с этим, когда вы пишете свои собственные.
Дмитрий

18

как сказал Джош Петри :

« Не построенный здесь синдром» ;

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

Я тестировал различные типы игровых движков, API рендеринга и тому подобное, в частности, Ploobs, UNITY WaveEngine, XNAFinalEngine, Love, Ogre и т. Д., И многое другое ... Я хотел начать писать игры - я скачал много, ища хороший удобный и хорошо документированная точка входа ...

Моя проблема, однако, была в то время, когда я понятия не имел, что происходит под двигателем. Я хотел хорошего контроля, и я хотел рамки, которые я знаю, как тыльную сторону моей руки. Мне пришла в голову идея «ЭЙ! Я думаю, что единственный способ узнать, как это работает и понять это, - это попытаться создать свой собственный движок целиком и полностью с нуля. Большая часть моей истории программирования была связана с веб-технологиями и решениями для обработки». - это была совершенно новая игра с мячом для меня.

Что я и сделал в итоге.

Поэтому я решил установить XNA, так как я уже знал C #, и начал думать о том, как или с чего мне начать. Мне нужна идея

Я решил, что, несмотря ни на что, я пойду прямо в 3D .

Разобраться с основами было круто - спрайт, но по мере того, как я прогрессировал, я обнаруживал новые барьеры и препятствия - моим первым реальным было ограничение партии . Моя цель состояла в том, чтобы создать игру, которая в любой момент могла бы отображать как минимум 10000 объектов в окне просмотра.

Я приступил к новому пути реализации Шейдерных инстансингов (и изучил HLSL, пока я там занимался), я отказался от встроенных в XNA объектов Model и Effect, чтобы вместо этого написать свои собственные замены. Сначала у меня были проблемы с пониманием потоков VBO; Я ломал вещи - я выходил в интернет, задавая вопросы об инстансинге, и продолжал, пока я, наконец, не понял, что делает GPU. Это окупилось; теперь у меня было более двадцати тысяч тестовых объектов, масштабирующихся в моем окне просмотра после пары дней отладки моего VBO с помощью PIX (dxsdk).

Теперь у меня было «некоторое» представление о том, как работают конвейеры рендеринга, но это еще не было сделано - я закончил тем, что создал свое собственное игровое состояние, камеру, пост-эффекты и объекты-сущности, отодвинув их от XNA Content Pipeline, создав собственный загрузчики (личная неприязнь к объекту XNB), создали сложную цепочку геометрии с сортировкой по глубине и разделенным состояниями, а также имели экземпляры спрайтов и текста, которые проецировались на игровую сцену.

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

Теперь мой двигатель был в основном стабильным и почти законченным. Он не идеален: скрипты честные, а графический интерфейс совсем не великолепен. Но я все еще любил это. Тысячи строк кода, ресурсов и мультимедиа спрятались в частном git-репозитории объемом 2 ГБ, и все головные боли, которые мне пришлось пережить, пытаясь сделать такой тип разработки, которого я никогда раньше не делал. Каждое препятствие, которое я преодолел, было извлеченным уроком и облегчением.

Я снял почти все, что хотел в нем.

Но в конце концов - я решил, что пришло время унизить ее. Столько, сколько я удовлетворил себя написанием такого огромного движка самостоятельно, по совету из сети и других приятелей gamedev, я решил, что я сделаю это снова - и сделаю это лучше - потому что теперь на этот раз я в основном знаю что я делаю.

Этот проект все еще находится в моем репозитории GIT.

Мой второй проход по написанию нового движка (на этот раз на MonoGame) проходит хорошо. Когда что-то ломается, это легче исправить. Меньше беспорядка. Я надеюсь публично показать мою игру где-то в этом году, потому что я, как правило, слишком привязан к своему коду.

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

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


13
Это больше похоже на бессвязный личный анекдот; Вы могли бы вероятно отредактировать это, чтобы сделать это намного более кратким, и это сделало бы лучший ответ.
Джош

2
Это, безусловно, отлично подходит для обучения, а также для создания игры, когда у вас есть время на все. Когда это действительно только ты. Но что, если вы когда-нибудь захотите сотрудничать с кем-то? Или работать в компании с другими программистами? Если кто-то хотел бы присоединиться к вашему проекту, не странно ли, что он должен будет читать ваш код - для них код других людей ... то, что вы НЕНАВИЖЕТЕ. Я считаю, что чтение кода тоже очень важный навык. Без обид, я уверен, что вы многому научились и написали классный движок - просто заметьте, что это еще не все.
Antont

Я знаю об этом, просто каждая моя работа с любым видом кода на любом языке всегда была для меня соло D;
Коди Морган

Должен сказать, я точно знаю , по каким причинам человек запускает свой собственный двигатель / инструмент / что угодно. Но у этого есть цена (как и все вещи) ... У меня такое чувство, что все боссы просто ненавидят это, когда вы не можете прочитать / понять самый дурацкий код из всех существующих, поэтому, пожалуйста, продолжайте в том же духе ** * тонна плохо написанного, плохо обслуживаемого кода без документации, просто почувствуйте его («реальный» мир). Не обижайся.
Quonux

Вот почему у нас, программистов, не может быть хороших вещей. Потому что мы всегда хотим делать все сами, а не использовать рабочие и проверенные методы. У меня есть навязчивая потребность писать все самому, но я постепенно учусь доверять другим, и пока это приносит мне больше пользы, чем зла :)
Maurycy

15

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

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

Если вы используете чей-то коммерчески доступный движок, и у вас нет исходного кода для этого движка (как правило, у вас его нет), то отладка любых проблем, которые возникают - даже внутри вашего собственного кода - идет быть монументально сложнее. И если вы столкнетесь с ошибкой внутри самого движка, вы не сможете их устранить самостоятельно. Как бы вы хотели, чтобы через неделю после даты релиза кто-то обнаружил ошибку сбоя в используемом вами движке - ошибку сбоя, которую вы не можете исправить, потому что она находится в проприетарном движке, к которому вы не обращаете есть исходный код? Я видел, как это произошло - у вас нет другого выбора, кроме как обратиться к поставщику в срочном порядке в службу поддержки и надеяться, что он сможет (и заинтересован) решить проблему для вас, пока вы копаетесь,

Разработка игр сложна, но отладка на несколько порядков сложнее. В моей книге все, что усложняет разработку игр, но облегчает отладку, является огромным выигрышем.


3
Это один большой плюс, который мы испытали при использовании движка с открытым исходным кодом (cocos2d-iphone). Мы можем отладить его точно так же, как и код, который мы написали. На самом деле я считаю, что способ думать об открытом исходном коде - это ваш код. Если есть ошибки, мы должны будем их исправить, как и в любой другой части нашего кода ..
antont

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

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

@TrevorPowell Очевидно, это сводится к сложности проекта и, как вы говорите, в каждом конкретном случае, но просто заново изобретать колесо (особенно если это большое колесо) необходимо серьезно рассмотреть с точки зрения экономии времени, не делая Это. Промежуточное программное обеспечение делает вещи проще. Как разработчики, мы верим, что всегда можем изобрести решение, чтобы сделать его лучше, не задумываясь о том, насколько хорошо это решение собрано вместе. Несколько ударов> переосмысление> Неправильное решение полностью
Тим

2
@Tim RE: «Middleware делает вещи проще», у меня, по-видимому, был совершенно другой опыт, чем у вас.
Тревор Пауэлл

9

Здесь есть очень хорошие ответы, но они упускают один важный дополнительный момент.

Многие из сегодняшних лицензируемых двигателей начинались как специализированные двигатели .

Давайте возьмем Unreal в качестве примера, потому что он такой вездесущий.

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

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

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


2
Стоит отметить, что в те времена, когда впервые создавались игры, такие как Unreal, просто не было другого выбора, как писать все с нуля. Это только последние пару лет, когда у нас есть выбор из N двигателей ...
joltmode

3

Существуют и другие причины, по которым студия может «строить» вместо «покупать» свои технологии:

  • Новые платформы : новая мобильная ОС, консоль или контроллеры. Подумайте о leapmotion, Google Glass и т.д.
  • Новая игровая механика и / или внутриигровые редакторы : подумайте о СЭЗ, несколько лет назад (2D против 3D)
  • Отсутствие хороших бесплатных редакторов игр с открытым исходным кодом . Отсутствие хорошей документации на существующий источник старых игр
  • Эволюция инструментов в студии toolchain (или добавление новых)
  • Цены на двигатели и лицензионные войны

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

Хорошие мотивы «купить» или «использовать» другие двигатели:

  • Повторное использование кода : движок, уже используемый в других играх, более протестирован, более стабилен и может иметь большинство необходимых функций, начиная с первого дня.
  • Расширение : вы можете расширить некоторые движки с открытым исходным кодом.
  • Бесплатно : или почти бесплатно, поскольку даже для бесплатных движков с открытым исходным кодом требуется некоторое время для изучения.

2

Историческая причина (в основном).
Что связано с ценообразованием.

Каждая игра, которую вы видели в Unreal или CryEngine в последние годы, должна была платить огромную сумму денег. Особенно, если вы хотите получить исходный код (т.е. вы хотели UE, а не только UDK.)

Но это изменилось. Теперь, когда началась ценовая гонка, каждый может позволить себе еще большие двигатели.
Что это значит...

  • Вы увидите гораздо больше игр, использующих как UE4, так и CryEngine.
    Хотя они не будут ААА-играми, какими они были.
  • Пользовательские требования и потребности для каждого проекта не исчезнут.
    См. Движок Warhammer40k / COH в Relic или тот, который генералы использовали в EA.
    Таким образом, даже если кто-то может позволить себе двигатели большего размера, он не обязательно предлагает лучший выбор.
  • На рынке есть и другие. Как Единство.
    Людям нравится его простота в использовании, высокая производительность и огромный запас ресурсов.
    Разумеется, Unity может развертываться практически на любой платформе.

Так что да. Потребности, цены в прошлом и тому подобное.


1
Я бы не назвал Хавок «сильно модифицированным».
Джош

Разве Havok не просто физический двигатель?
Филипп

Да, и GW2 не особо отметил, что я могу вспомнить.
Джош

Ты имеешь в виду (ie.: you want UE, not UDK only.)?
Кивон

#JoshPetrie: Извините, если честно, я не имею опыта в Havok / никогда не играл с ним. Поэтому я наткнулся на файл ЛИЦЕНЗИИ GW2, а затем несколько дней назад зашел на его вики-страницу и увидел Хавока. Тогда у меня было какое-то старое воспоминание о том, чтобы увидеть «Havok» в начале игры, где я думал, что это двигатель. Но потом я тоже посмотрел на Хавока и понял, что это физический движок. tl; dr: Я все перепутал с Havok. || Филипп: Это немного больше, но на самом деле это не игровой движок, мой плохой. || #Keavon: Верно, исправлено. Благодарность!
Apache

0

А как насчет организации команды?

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

Итак, мне нужна группа поддержки, чтобы сделать это. Но это увеличивает затраты: больше людей, больше мест, больше телефонных линий, больше администрации ...

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

Для начинающей компании это неплохой вариант использовать, а не строить. И, после получения критической массы доходов, может быть, может быть, вы захотите создать свой собственный двигатель ...


0

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

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


0

Мой ответ отличается от существующих, поэтому я добавляю его, хотя уже поздно:

Если вы возьмете пример Valve из вопроса или серию «Ведьмак», процесс будет таким:

  • Лицензировать двигатель
  • Модифицировать / адаптировать движок к вашей цели
  • Выпусти игру и заработай деньги
  • Создать собственный движок для следующей игры

Такой же подход применяется практически всеми финансово обоснованными разработчиками, которые разрабатывают свой собственный движок. Модифицируя движок, они накапливают знания о том, как работает движок, и сталкиваются с конструктивными ограничениями, вытекающими из лицензированного движка. В конце концов они обладают внутренними знаниями, необходимыми для создания движка, наличными для финансирования создания движка и проектом, который выиграет от выделенного движка. На этом этапе причина для создания двигателя: потому что это разумно.


-2

мой учитель программирования сказал нам, используйте только API / методы / классы / функции, которые вы знаете, как построить

потому что, если вы не знаете, как его построить и используете чьи-то рабочие шансы, вы не знаете, как это работает, и когда вы не знаете, как что-то работает, то вы гораздо более склонны к ошибкам и проблемам, а также к стенам путаницы

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

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

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

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

во всяком случае, я надеюсь, что я дал понять, на что я пытался указать


6
-1 Если вы работаете над каким-либо значительным проектом, от вас ожидают, что вы будете использовать функции / классы, которые вы не знаете, как они были написаны, и вы не сможете написать их самостоятельно, не изучив количество книг на тема. Я не говорю о том, что должен знать каждый программист, но игровой движок - это огромный проект, и ожидается, что программист X, специализирующийся на теме X, не обладает знаниями в теме Y и, следовательно, должен использовать эту функцию, я также не подразумевается, что вы не должны знать, как использовать API, который вам следует, но у вас может не хватить знаний, чтобы написать его.
concept3d

2
Знает ли ваш учитель, как собрать автомобиль из химических элементов с нуля? Или он ведет это, предполагая, что это только работает ;-)
Кромстер говорит, что поддерживает Монику

1
@ concept3d есть разница между работой над проектом, где кто-то другой разрабатывает те функции / классы, которые вы используете, потому что обычно, если вы что-то не понимаете, это легко объяснить, программисту, который использует кодовые классы / функции / библиотеки, он / она не знает, что это глупый человек, даже классы и API, доступные публично, поставляются с руководствами и вики, которые объясняют, что делают эти API или функции, просто ожидать, что использовать его, не зная, что он делает, - все равно что пытаться плавать в глубокие воды, не зная, как плавать, и действительно невежественны и подвержены ошибкам
thingybingytie

@ hopjoppe5 Если вы проверите принятый ответ, это единственные причины, по которым люди создают свои собственные технологии. Многие библиотеки / код аутсорсинга в реальном мире, и вы должны использовать его. Чтение руководств отличается от знания реализации, для некоторых алгоритмов вам даже не рекомендуется внедрять их самостоятельно, и их должны применять эксперты в данной области, если у вас есть какой-либо практический опыт, вы поймете это. Знать все невозможно.
concept3d

Одной из основных причин абстракции является написание кода, чтобы люди, которые не знают, как он работает, все еще могли его использовать. При работе над игрой, которая больше, чем pong, маловероятно, что вы знакомы с каждым фрагментом кода. И в большинстве случаев это хорошо, потому что это означает, что вы можете сосредоточить свое внимание на том, над чем вы сейчас работаете, а не беспокоиться о том, как система ввода может обработать ваш запрос на событие «On Action Key Down».
Айдиакапи,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.