¿Por qué un desarrollador de juegos escribiría su propio motor en lugar de utilizar los existentes?


41

He observado que muchos desarrolladores de juegos grandes y conocidos a menudo desarrollan sus propios motores. Los ejemplos incluyen Valve, Crytek, Ubisoft, Epic Games y Square-Enix.

¿Podría ser simplemente porque pueden, o es probable que los motores existentes no cumplan con los requisitos suficientes, por lo que desarrollaríamos los nuestros? Apenas puedo imaginar un juego que requiera un motor específico. Los gustos de Unity o Unreal son simplemente suficientes para hacer cualquier tipo de juego; incluso si no, tienen código fuente, que puede modificarse para satisfacer incluso algunas necesidades extraordinarias.

¿Por qué un desarrollador de juegos escribiría su propio motor en lugar de utilizar los existentes?



1
No quieren licenciar los motores de juego de otras compañías y pagarles.
János Turánszki

Supongo que eso es lo que haces cuando tienes 9K + empleados por ahí ...
glampert

3
Hay varios contraejemplos de grandes estudios que crean títulos AAA utilizando motores de terceros como Unreal o CryEngine .
Philipp

3
Valve comenzó usando el motor Quake, y finalmente escribió el suyo para juegos posteriores. A menudo es cuestión de aprender a usar lo que está disponible, y finalmente querer lograr algo más de lo que ofrece el motor existente. En ese punto, tiene que hacer grandes modificaciones o rodar las suyas.
Nairou

Respuestas:


53

Hay varias razones por las que un estudio puede optar por "construir" en lugar de "comprar" su tecnología:

  • Tecnología heredada; un estudio puede haber comenzado a construir su propia cadena de herramientas antes de que existiera un middleware viable y viable para él.
  • Requisitos específicos; un estudio puede tener una colección particular de requisitos que no es adecuada para el middleware existente o
  • Preocupaciones presupuestarias; Es posible que un estudio no pueda pagar los gastos u obligaciones contractuales del middleware existente.
  • "Síndrome no construido aquí"; El liderazgo técnico de los estudios puede ser cauteloso (razonable o irrazonablemente) de la tecnología que no construyeron y, por lo tanto, no comprenden completamente.

En general, tiene sentido poseer y controlar las cosas que son críticas para el éxito de su negocio, y externalizar las que no lo son.

Para algunos estudios, el aspecto de diseño o narración de sus juegos puede ser el recurso crítico que esperan capitalizar para el éxito. Para esos estudios, tiene sentido simplemente comprar tecnología que permita a sus diseñadores realizar la visión adecuada.

Para otros, la tecnología puede ser la base del éxito. Los estudios que construyen MMO, por ejemplo, generalmente necesitarán construir esa infraestructura ellos mismos porque es fundamental para su éxito (y el middleware existente es generalmente inapropiado, al menos para títulos más grandes, "AAA").

Tenga en cuenta que algunos de los estudios que enumeró (Crytek y Epic en particular) básicamente han dejado de intentar ser fuerzas dominantes en el mercado de juegos directamente, y casi con certeza hacen mucho más como vendedores de middleware que como desarrolladores de juegos.


20
Añadiría que a veces hay ventajas para las tecnologías que se "construyen aquí". Un ejemplo es cómo Unity3D cambia sus EULA en cada versión y agrega restricciones extrañas, como no "juegos de apuestas". Cuando otorga una licencia a un técnico, está a merced del licenciante para no dar la vuelta y revocar la licencia sin ningún motivo en particular (como sucede con los derechos de propiedad intelectual para hacer juegos con licencia) o decide cobrarle para que repare sus errores.
Skrylar

en serio, ¿Unity dice "no juegos de apuestas"? ¡Incluso solían tener una página específica sobre juegos de azar en la sección Comunidad de su sitio web!
jhocking

La página de Unity aquí unity3d.com/industries/gambling dice que puede comprar una "licencia de Unity Gambling". No he encontrado un precio para eso, pero parece que todavía te permiten hacer los juegos de apuestas siempre que pagues por una licencia especial.
Alex

1
Además, es más fácil comenzar con lo que ya sabe y terminar construyendo un motor, sin siquiera saber qué es un motor. Un motor no es más que una colección de casos de uso; Si estás tratando de reducir la redundancia, terminas escribiendo un motor, y si estás tratando de construir el juego, terminas con un sistema monolítico. Es muy muy difícil obtener un motor de juego y aprender a hacer que muestre un píxel, y luego darse cuenta de que no puede hacerlo porque ve todo como una textura. No tienes que lidiar con eso cuando escribes el tuyo.
Dmitry

18

como dijo Josh Petrie :

" Síndrome no construido aquí ";

También estoy escribiendo mi propio motor, y supongo que la razón será diferente para cada desarrollador, pero de hecho, generalmente no me gusta trabajar en el código de otras personas. Soy compulsivo en el sentido de que si siento que podría construirlo yo mismo, entonces no tiene sentido conformarse con otra cosa .

Probé varios tipos de motores de juegos, API de renderizado y otros, en particular Ploobs, UNITY WaveEngine, XNAFinalEngine, Love, Ogre, etc. muchos más ... Quería comenzar a escribir juegos: descargué mucho buscando un buen producto y punto de entrada bien documentado ...

Sin embargo, mi problema era que en ese momento no tenía idea de lo que estaba sucediendo debajo del motor. Quería un buen control y un marco que conozco como el dorso de mi mano. Se me ocurrió la idea "¡HEY! Creo que la única forma de aprender cómo funciona y entenderlo es intentar construir mi propio motor por completo y completamente desde cero. La mayor parte de mi historial de programación fue con soluciones web y de procesamiento - Este fue un juego de pelota completamente nuevo para mí.

Que es lo que terminé haciendo.

Así que elegí configurar XNA ya que ya conocía C #, y comencé a pensar cómo o dónde debería comenzar. Necesitaba una idea

Decidí que, sin importar qué, iría directamente a 3D .

Aprender lo básico fue genial: las cosas del lote de sprites, pero a medida que avanzaba terminé descubriendo nuevas barreras y obstáculos, siendo el primero el límite de lotes . Mi objetivo era crear un juego que pudiera representar al menos 10000 entidades en el punto de vista en cualquier momento.

Me embarqué en un nuevo viaje de implementación de la Instancia basada en Shader (y aprendí HLSL mientras estaba en eso), abandoné los objetos de modelo y efecto integrados de XNA para escribir mis propios reemplazos. Al principio tuve problemas para entender las transmisiones de VBO; Rompí las cosas: me conecté en línea haciendo preguntas sobre las instancias y seguí hasta que finalmente entendí lo que estaba haciendo la GPU. Valió la pena; ahora tenía más de veinte mil entidades de prueba haciendo zoom en mi ventana gráfica después de un par de días de depuración de mi VBO con PIX (dxsdk).

Ahora tenía "alguna" idea de cómo funcionaban las canalizaciones de renderizado, pero aún no había terminado: terminé creando mi propio estado de juego, cámara, efectos posteriores y objetos de entidad, alejándome de la canalización de contenido XNA construyendo el mío. los cargadores (aversión personal hacia la cosa XNB), crearon una complicada cadena de geometría separada por estado de fusión y separada por estado de mezcla y también tuvieron instancias de sprites y texto proyectados en la escena del juego.

Seguí agregando, arreglando, cambiando y experimentando con esto continuamente durante casi un año entero. Al final, salió bastante bien. Ahora entendía lo que estaba sucediendo debajo del capó, porque lo creé: mi bebé.

Ahora mi motor estaba mayormente estable y casi terminado. No es perfecto: las secuencias de comandos son suaves y la GUI no fue excelente en absoluto. Pero aún así me encantó. Miles de líneas de código, activos y medios, encerrados en un repositorio git privado de 2GB, y todos los dolores de cabeza que tuve que pasar tratando de hacer un tipo de desarrollo que nunca antes había hecho. Cada obstáculo que superé fue una lección aprendida, y un alivio.

Saqué casi todo lo que quería en él.

Pero al final, decidí que era hora de menospreciarla. Por mucho que me convencí de escribir un gran motor de este tipo por mí mismo, con el asesoramiento de la red, y otros amigos GameDev, decidí que voy a hacer todo de nuevo - y hacerlo mejor - porque ahora esta vez sobre todo sabe Que estoy haciendo.

Ese proyecto todavía se encuentra escondido en mi repositorio GIT.

Mi segundo paso al escribir un nuevo motor (esta vez en MonoGame) está progresando bien. Cuando algo se rompe, es más fácil de arreglar. Menos desorden. Espero mostrar públicamente mi juego en algún momento de este año, porque tiendo a estar un poco "demasiado" apegado a mi código.

Al final, escribir mi propio motor es cómo aprendí 'cómo' hacerlo, al tiempo que puedo decir que sé y entiendo exactamente qué hace cada componente y cómo se supone que funcionan. De hecho, ODIO leer el código de otras personas, especialmente para grandes proyectos indocumentados. Quiero que todo lo que uso sea construido por mí.

Aunque solo soy yo. Dudo que alguna vez use un motor prefabricado, probablemente porque creo que es más divertido para mí escribir mis propios marcos que sentarme y lidiar con el código de otra persona: control total.


13
Esto se lee mucho más como una anécdota personal laberíntica; probablemente podría editar esto para hacerlo mucho más conciso y sería una mejor respuesta.
Josh

2
Todo esto es genial para aprender y también para hacer tu juego cuando tienes tiempo para hacer todo. Cuando de verdad eres solo tú. Pero, ¿qué pasa si alguna vez quieres colaborar con alguien? ¿O trabajar en una empresa con otros programadores? Si a alguien le gustaría unirse a su proyecto, ¿no es un poco extraño que se suponga que lean su código? Para ellos, el código de otras personas ... lo que usted ODIA. Me parece que la lectura del código también es una habilidad muy importante. Sin ofender, estoy seguro de que has aprendido mucho y has escrito un motor genial, solo una nota de que no es todo lo que hay que hacer.
Antont 05 de

Soy consciente de eso, cada trabajo que he tenido que involucra cualquier tipo de código en cualquier idioma, siempre ha sido solo para mí D;
Codie Morgan

Debo decir que sé exactamente por qué razones una persona lanza su propio motor / herramienta / lo que sea. Pero tiene un precio (como todas las cosas) ... Tengo la sensación de que todos los jefes simplemente lo odian cuando no puedes leer / entender el código más desagradable que existe, así que por favor, adelante y tírate como ** * Tonelada de código mal escrito mal mantenido sin documentación, solo inténtelo (el mundo "real"). Sin ofender.
Quonux

Esa es la razón por la que nosotros, los programadores, no podemos tener cosas buenas. Porque siempre queremos hacer todo nosotros mismos en lugar de usar métodos de trabajo y confiables. Tengo una necesidad compulsiva de escribir todo yo mismo, pero poco a poco estoy aprendiendo a confiar en los demás y hasta ahora me hace más bien que mal :)
Maurycy

15

La razón clave absoluta para escribir su propio motor (y me sorprende que nadie lo haya llamado aún) es para la depuración .

Si ha escrito un juego grande y complicado, y tiene un error de bloqueo, y tiene el código fuente (y está íntimamente familiarizado con ese código fuente en virtud de haberlo escrito), simplemente puede adjuntar un depurador a el proceso y encuentre la causa del bloqueo. Hecho.

Si está utilizando el motor comercialmente disponible de otra persona y no tiene el código fuente de ese motor (normalmente no lo tiene), entonces se eliminará cualquier problema que surja, incluso dentro de su propio código. ser monumentalmente más difícil. Y si se encuentra con un error dentro del motor, no podrá resolverlo usted mismo. ¿Cómo le gustaría estar una semana fuera de su fecha de lanzamiento y que alguien descubra un error de bloqueo en el motor que está utilizando? Un error de bloqueo que no puede solucionar porque está dentro de un motor patentado en el que no tiene el código fuente? He visto que esto sucede: no tiene más remedio que presentar una llamada de soporte urgente con el proveedor y esperar que puedan (y estén interesados ​​en) solucionar el problema por usted, mientras se pelea,

El desarrollo del juego es difícil, pero la depuración es mucho más difícil. En mi libro, cualquier cosa que dificulte el desarrollo del juego pero la depuración sea más fácil es una gran ganancia neta.


3
Esta es una gran ventaja que hemos experimentado con el uso de un motor de código abierto (cocos2d-iphone). Podemos depurarlo exactamente de la misma manera que el código que hemos escrito. De hecho, encuentro que la forma de pensar en código abierto es que es su código. Si existen errores que tendremos que solucionarlos, como en cualquier otra parte de nuestro código ..
Antont

1
Esto se puede decir de cualquier middleware. El código de depuración es el 80% del trabajo de un programador, y el manejo de middleware es un problema común con la tecnología en la que nos encontramos hoy con más middleware del que podemos contar. Aprender a superar eso es solo parte del trabajo. Si el motor no se rompe, algo más sobre lo que no tiene control lo hará. Menos partes móviles es una buena idea, pero cuando se complica como el desarrollo del juego, tendrás que lidiar con muchas de todas formas.
Tim

@Tim Estoy totalmente en desacuerdo: que una cosa externa podría comportarse mal de una manera difícil de depurar no implica que debamos encogernos de hombros y resignarnos a dejar que todo se comporte de manera difícil de depurar. Obviamente, es necesario tomar las cosas caso por caso, pero un motor es un gran sistema donde a menudo acechan errores difíciles . ¿Por qué no querrías eso bajo tu control, si es que puedes permitirte hacerlo tú mismo?
Trevor Powell

@TrevorPowell Obviamente, todo se reduce a la complejidad del proyecto y, como usted dice, caso por caso, pero simplemente reinventar una rueda (especialmente si es una rueda grande) debe considerarse seriamente con respecto al tiempo ahorrado al no hacer eso. El middleware hace las cosas más fáciles. Como desarrolladores, creemos que siempre podemos reinventar una solución para mejorarla sin tener en cuenta qué tan bien se combina esa solución. Algunos golpes> reinvención> La solución equivocada por completo
Tim

2
@Tim RE: "Middleware hace las cosas más fáciles", aparentemente he tenido experiencias muy diferentes a las tuyas.
Trevor Powell

9

Aquí hay muy buenas respuestas, pero les falta un punto adicional importante.

Muchos de los motores actuales con licencia comenzaron como motores dedicados .

Tomemos Unreal como ejemplo porque es muy ubicuo.

Hoy, cuando piensas en Unreal, tiendes a pensar en un motor que autorizas y puedes usar en lugar de tener que construir el tuyo propio, pero ese no fue siempre el caso, y alguna vez el motor de Unreal ni siquiera existía como Una entidad separada.

Había una vez un juego llamado Unreal . Los desarrolladores decidieron construir su propio motor en lugar de licenciar uno existente . Avance rápido a través de varias iteraciones y ese motor se convierte en el motor Unreal que conocemos hoy.

El punto es que este es un problema de huevo y gallina. Cada bit de middleware que puede licenciar comenzó en algún lugar, y a menudo no comenzó como middleware (a veces ni siquiera fue escrito con la intención de convertirse en middleware y su estado actual es efectivamente un accidente ). La gente escribe sus propios motores porque, en última instancia, alguien tiene que escribir el motor, y el motor dedicado de hoy podría convertirse en el middleware con licencia del mañana.


2
Vale la pena señalar que, en el pasado, cuando los juegos como Unreal se construyeron por primera vez, simplemente no había otra opción que escribirlo todo desde cero. Es sólo el pasado par de años en los que tenemos una opción de N motores ...
joltmode

3

Hay otras razones por las que un estudio puede optar por "construir" en lugar de "comprar" su tecnología:

  • Nuevas plataformas : nuevo sistema operativo móvil, consola o controladores. Piense en leapmotion, google glass, etc. El soporte multiplataforma es difícil
  • Nuevas mecánicas de juego y / o editores en el juego : piense en FEZ, hace algunos años (2D vs 3D)
  • Falta de buenos editores de juegos de código abierto gratuitos . Falta de buena documentación sobre la fuente existente de juegos antiguos
  • Evolución de las herramientas en la cadena de herramientas de estudio (o agregar nuevas)
  • Precios de motores y guerras de licencias

También estoy de acuerdo con las solicitudes / necesidades específicas y los precios de los motores y las guerras de licencias obligan a algunos estudios a implementar algunos motores.

Los buenos motivos para "comprar" o "usar" otros motores son:

  • Reutilización de código : un motor ya utilizado en otros juegos está más probado, es más estable y puede tener la mayoría de las características necesarias, desde el primer día.
  • Extender : puede extender algunos motores de código abierto.
  • Gratis : o casi gratis, ya que incluso los motores de código abierto gratuitos, necesitan algo de tiempo de desarrollador para aprender.

2

Razón histórica (principalmente).
Lo que está relacionado con los precios.

Cada juego que viste ejecutando Unreal o CryEngine en los últimos años tuvo que pagar una gran cantidad de dinero. Especialmente si desea obtener el código fuente (es decir: quería UE, no solo UDK).

Pero esto cambió. Ahora todos pueden permitirse motores aún más grandes, cuando comenzó la carrera de precios.
Lo que eso significa ...

  • Verás muchos más juegos usando UE4 y CryEngine.
    Sin embargo, no serán juegos AAA como lo han sido.
  • Los requisitos y necesidades personalizados para cada proyecto no desaparecerán.
    Vea el motor Warhammer40k / COH en Relic, o el que los Generales usaron en EA.
    Entonces, incluso si alguien puede permitirse los motores más grandes, no necesariamente ofrecen una mejor opción.
  • Hay otros en el mercado. Me gusta la unidad.
    A la gente le encanta por su facilidad de uso, rendimiento rápido y la gran tienda de activos.
    Por supuesto, Unity puede desplegarse en casi cualquier plataforma.

Así que sí. Necesidades, precios en el pasado y tal.


1
No llamaría a Havok "muy modificado".
Josh

¿No es Havok solo un motor de física?
Philipp

Lo es, y GW2 no le prestó mucha atención a eso.
Josh

No quiere decir (ie.: you want UE, not UDK only.)?
Keavon

#JoshPetrie: Lo siento, para ser honesto, no tengo experiencia en Havok / nunca jugué con él. Así que me topé con el archivo de LICENCIA de GW2 y luego visité su página wiki hace unos días y vi a Havok. Luego tuve un viejo recuerdo acerca de ver "Havok" al comienzo del juego, donde pensé que ES el motor. Pero luego también busqué a Havok en ese entonces y supe que era un motor de física. TL; DR: Mezclé cosas sobre Havok. || #Philipp: Es un poco más que eso, pero de hecho no es un motor de juego, mi mal. || #Keavon: Correcto, fijo. ¡Gracias!
Apache

0

¿Qué pasa con la organización del equipo?

Detrás de las cosas de depuración están la documentación y el soporte, no el código, porque al final no quería que mi grupo de construcción tocara el código de mi propio motor. Eso podría ser un desastre.

Entonces, necesito un grupo de apoyo para hacer eso. Pero eso eleva los costos: más personas, más lugares, más líneas telefónicas, más administración ...

Una solución a esto puede ser subcontratar ... a una empresa de middleware, liberando recursos para mi negocio de hacer juegos, es decir, para el grupo creativo y los escritores.

Para una empresa nueva no es una mala opción usar y no construir. Y, después de obtener una masa crítica de ingresos, puede ser, solo puede ser, querrás construir tu propio motor ...


0

bien. para la mayoría de los juegos que usan su propio motor creado por sus desarrolladores. a menudo. No pueden hacer cosas con un motor de terceros. así que hacen lo suyo para facilitar el desarrollo de su propio juego. o posible al menos.

y muchos juegos que usan su propio motor en general. trabaja mejor. porque son más personalizados y se ajustan al 100% a su tarea. y el juego en sí se siente de manera diferente. es realmente fácil jugar un juego y decir que está hecho por. motor irreal o lo que sea. motor más personalizado en general y debería dar como resultado un juego que se siente único. se ve único y funciona de manera única y debería funcionar mejor que un juego creado en un motor prefabricado.


0

Mi respuesta difiere de las existentes, así que la agrego aunque sea tarde:

Si toma el ejemplo de Valve de la pregunta, o la serie Witcher, el proceso fue:

  • Licencia un motor
  • Modifique / adapte el motor a su propósito
  • Lanza el juego y genera dinero
  • Crea tu propio motor para el próximo juego

Casi todos los desarrolladores financieramente razonables que desarrollan su propio motor adoptan el mismo enfoque. Al modificar un motor, acumulan conocimiento sobre cómo funciona un motor y se topan con restricciones de diseño que resultan de un motor con licencia. Al final, tienen el conocimiento interno necesario para crear un motor, el efectivo para financiar la creación de un motor y un proyecto que se beneficiará de un motor dedicado. En ese momento, la razón para construir un motor es: porque es lo más inteligente.


-2

mi maestro de programación nos dijo, solo use las API / métodos / clases / funciones que usted sabe cómo construir

porque si no sabes cómo construirlo y estás utilizando el trabajo de otra persona, es probable que no sepas cómo funciona y cuando no sabes cómo funciona algo, entonces eres más propenso a errores y problemas y a golpear paredes de confusión

aprender cosas simples puede, cuando se combina, dar como resultado problemas extraños, y mucho menos algo complejo como un motor de juego, especialmente cuando se supone que debes usar ese motor de juego para ejecutar tu juego, lo que puede generar muchos resultados y problemas inesperados

y el motor del juego no sigue el código lógico o cualquier otra lógica cuando se construyen, seguro que hay algunas cosas que se pueden esperar, pero en realidad todo se construirá en base a la comprensión y el conocimiento de alguien de algún lenguaje de programación o cómo funciona algún sistema

por ejemplo, si elijo escribir una ecuación matemática, puedo escribirla de tantas maneras que puedo representarla con polinomios, cálculo diferencial o geometría básica o álgebra o lo que me convenga, pero a veces escribiría en cierta forma / formato porque quiero para poder manipular lo que está fácilmente disponible, como si planeara hacer una gran cantidad de manipulación de vértices, podría escribir este modelo matemático usando geometría básica, sin embargo, si quisiera cambiar la curva usando gradientes, podría centrarme en el cálculo diferencial para poder para manipular fácilmente los gradientes, etc. y lo mismo ocurre con lo que sea, planeo tener un acceso más fácil a

y, a veces, el motor del juego actual puede no darme la flexibilidad de lo que pretendo hacer o incluso tal vez te da esa opción, pero es muy difícil hacerlo porque el motor del juego se centra en las fuerzas físicas como su principal fuente de movimiento y manipulación de objetos en el juego

de todos modos espero haber dejado en claro lo que estaba tratando de señalar


66
-1 Si trabaja en un proyecto de tamaño respetable, se espera que use funciones / clases que no sabe cómo se escribió, y es posible que no pueda escribir uno sin tener que estudiar la cantidad de libros en el tema. No estoy hablando de lo que todo programador debe saber, pero un motor de juego es un gran proyecto, y se espera que el tema X especializado del programador X no tenga conocimiento en el tema Y y, por lo tanto, tenga que usar la función, tampoco estoy lo que implica que no deberías saber cómo usar la API, pero es posible que no tengas el conocimiento suficiente para escribir una.
concept3d

2
¿Su maestro sabe cómo construir un automóvil completo a partir de elementos químicos desde cero? ¿O lo conduce asumiendo que simplemente funciona ;-)
Kromster dice que apoya a Mónica el

1
@ concept3d hay una diferencia entre trabajar en un proyecto donde alguien más diseña esas funciones / clases que usa, porque generalmente si no comprende algo, puede explicarse fácilmente, un programador que utiliza clases de código / funciones / bibliotecas. / ella no sabe que es una persona tonta, incluso las clases y las API que están disponibles públicamente vienen con manuales y wiki que explican qué hacen esas API o funciones, solo esperar usarlo sin saber lo que hace es como intentar nadar en aguas profundas sin saber nadar, y realmente ignorante y propenso a errores
thingybingytie

@ hopjoppe5 Si marca la respuesta aceptada, estas son las únicas razones por las que las personas crean su propia tecnología. Muchas de las bibliotecas / códigos se subcontratan en el mundo real, y debe usarlo. Leer los manuales es diferente de conocer la implementación, para algunos algoritmos incluso no se recomienda implementarlo usted mismo y debe ser implementado por expertos en el tema, si tiene alguna experiencia en el mundo real lo entenderá. Saberlo todo es imposible.
concept3d

Una de las principales razones de la abstracción es escribir código para que las personas que no saben cómo funciona puedan usarlo. Cuando trabajas en un juego más grande que el pong, no es probable que estés familiarizado con cada código. Y en la mayoría de los casos eso es bueno, porque significa que puede concentrar su mente en lo que está trabajando en este momento, en lugar de preocuparse por cómo el sistema de entrada podría manejar su solicitud de un evento "On Action Key Down".
Aidiakapi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.