¿Cuáles son los pros y los contras de incorporar Lua en un juego de C ++?

37

Tengo un libro de programación de juegos C ++ y tiene una sección Lua. Empecé a leer la sección Lua, y suena interesante, pero no puedo determinar las ventajas y desventajas de usar Lua en mi juego C ++. El único beneficio que puedo pensar actualmente es que puede hacer algunas actualizaciones de codificación, a través de Lua, sin tener que volver a compilar. Aparte de eso, no puedo pensar en nada. ¿Cuáles son las ventajas y desventajas de agregar Lua a un juego de C ++?

Se agradecerían ejemplos.

Ryan
fuente
De acuerdo en que es similar a esas preguntas, pero lo importante aquí son los 'contras'.
Jonathan Dickinson
@JonathanDickinson las respuestas no apuntan en esa dirección, aunque ... básicamente dicen lo mismo que en la pregunta vinculada.
bummzack

Respuestas:

33

El único beneficio que puedo pensar actualmente es que puede hacer algunas actualizaciones de codificación, a través de Lua, sin tener que volver a compilar.

No descarte la utilidad de esto tan fácilmente. Usted no entiende lo productivo que será hasta que quitas el paso recompilación.

El "flujo" es un concepto psicológico bastante bien entendido cuando se trata de trabajar. El flujo es esa sensación que tienes cuando estás enfocado en una actividad, cuando estás analizando y resolviendo problemas casi sin pensar, etc. Eres más productivo cuando estás "fluyendo".

Los tiempos de compilación arruinan todo eso. Es difícil mantenerse en el flujo si tiene incluso una compilación de 10 segundos entre probar algo.

Cuando estás desarrollando un juego, lo que generalmente tienes es un "ciclo cerrado". Tienes una idea, codificas una prueba para ver si funciona y luego la pruebas. Si no funciona, modifíquelo e intente nuevamente. El tiempo de "código para probar" es muy importante para mantener el flujo. Conseguir que sea lo más pequeño posible es crucial.

Lo que Lua (o cualquier lenguaje de script incorporado) le permite hacer es probar los cambios, no solo sin "compilar", sino vivir en el juego . Dependiendo de cómo construyas tu juego, puedes ejecutar un comando que reiniciará el juego con nuevos scripts sin tener que parar y volver a cargar datos, etc. No solo no tiene que volver a compilar, no tiene que volver a ejecutarlo.

La capacidad de hacer esto, dado el soporte adecuado del motor, puede aumentar dramáticamente la productividad.


Otro beneficio importante de las secuencias de comandos es la capacidad de no importarles. Si ha pasado mucho tiempo escribiendo C ++, se sorprenderá de cuánto tiempo pasa más de minutos. Donde se borra la memoria. Donde esto se libera. Incluso si está usando en shared_ptrtodas partes, solo el hecho de escribir todos esos nombres de tipo variable lo ralentiza.

En un lenguaje de secuencias de comandos de tipo dinámico, no tiene que preocuparse. El alcance es simple. Las funciones son objetos de primera clase; no tienes que construir functors manualmente. Es muy fácil hacer algunas cosas.

Ahora eso tiene aspectos negativos, si no eres un programador disciplinado. Es muy fácil usar globals en Lua (aunque hay formas de evitarlo). No preocuparse significa que puedes ser muy descuidado cuando codificas.

Pero, de nuevo, ser muy descuidado puede tener ventajas .


Otra ventaja de Lua es que es un buen lenguaje de descripción de datos. Al igual que JSON es solo un archivo JavaScript que crea y devuelve una matriz / tabla, puede crear scripts Lua que devuelvan tablas.

Esto es útil para los archivos de configuración; El formato de tabla de Lua es mucho mejor que los formatos .ini. El formato sigue siendo bastante limpio, compacto y extensible.

Ah, y sigue siendo un script Lua, por lo que puede realizar una lógica real. La desventaja de eso es ... bueno, es un script Lua, por lo que puede realizar una lógica real . Eso podría ser desastroso en el juego, ya que el usuario podría comenzar a arruinar las cosas.

Pero en realidad, esto es fácil de resolver. Lua está diseñado para incrustar, lo que significa que el aislamiento es bastante fácil. De hecho, un nuevo estado de Lua no proporciona nada por defecto; tienes que hacer algo para exponer incluso la más básica de las bibliotecas estándar de Lua. El acceso a los archivos, el acceso al estado del juego, etc., está habilitado, no inhabilitado. Y cada estado Lua está separado el uno del otro. El estado Lua que usa para los scripts AI no tiene que ser el estado Lua que usa para los archivos de configuración.

De hecho, tengo un código que le permite registrar muchas bibliotecas estándar de Lua, pero revisa y elimina todos los archivos IO. En última instancia, lo peor que podría hacer un archivo de configuración basado en un script Lua es hacer que su juego se bloquee inmediatamente al ejecutarlo, quedando sin memoria. Y dado que no está compartiendo estos archivos de configuración manualmente, eso no sería muy divertido para un hacker.


Yo diría que el mayor inconveniente de cualquier lenguaje de script es la depuración. La mayoría de los lenguajes de script no tienen depuradores, y Lua no es diferente. Lua tiene todas las herramientas que uno necesitaría para construir herramientas de depuración. Pero en realidad no tiene un depurador incorporado. Tienes que armar uno. Y eso requerirá un grado razonable de trabajo.

O puede hacerlo con "depuración printf". Realmente depende de cuánto código Lua escribas.

Nicol Bolas
fuente
1
fluir no siempre es algo bueno; hacer cosas automáticamente a veces significa no tomarse el tiempo para caminar sobre alternativas de diseño.
Lurscher
10
@lurscher: el diseño es lo que haces antes de sentarte a codificar. Debería haber resuelto todas esas alternativas de diseño antes de comenzar a escribir, probar y depurar su código.
Nicol Bolas
23

Donde yo trabajo:

Pros:

  • Mejoras en el tiempo de iteración . Nuestro juego está configurado para sondear un sistema de archivos host en busca de cambios y automáticamente "sorber" los cambios. (Solo entran en vigencia en el siguiente archivo abierto, pero en la práctica, esa es una mejora importante: vuelva a cargar el nivel y sus nuevos cambios de lua entrarán de inmediato).
  • Integración de consola . Cualquier funcionalidad de depuración se puede conectar a una consola tradicional de estilo Quake con un REPL. Para compilaciones internas, incluso podemos conectar un lua REPL a un socket simple que habla telnet, y tenemos control de red sobre nuestro juego.
  • API reducida y curva de aprendizaje inferior . Los artistas y diseñadores no técnicos pueden participar en algunas tareas que normalmente serían cuellos de botella del programador.
  • Análisis especializado de código estático . Es fácil analizar la salida luac -ly echar un vistazo al código de bytes para hacer un análisis; También es bastante fácil analizar la mayoría de los archivos fuente lua, especialmente si tiene una convención de codificación. Podemos hacer cumplir la convención local. También puede buscar metalua para obtener aún más potencia aquí.
  • gestión de errores . Si nuestra API está libre de fallas, incluso si lua hace algo tonto, podemos atraparlo y recuperarlo usando lua_pcall.
  • Extensión API fácil . Escribir una nueva función para la API Lua <-> C ++ no es demasiado difícil. También hay paquetes que ayudarán a automatizar esto.
  • fuente simple . ¡Hacer cambios para, por ejemplo, evitar las matemáticas de punto flotante en el intérprete lua (importante en algunas plataformas integradas) o para optimizar sistemas particulares no es demasiado difícil!
  • metatables . Éstos son impresionantes. Tanto potencial para hacer cosas interesantes en tiempo de ejecución. Tenemos "tablas virtuales" que en realidad no tienen contenido y realizan una búsqueda en una estructura de datos complicada en el lado C ++ de nuestros juegos.
  • corrutinas . Ser capaz de detener y reanudar, por ejemplo, los scripts de comportamiento de AI es increíble. Sin embargo, se necesita un poco más de inteligencia por parte del scripter lua, todavía estamos trabajando en cómo hacer que esto sea más "seguro" con nuestro motor.

Contras:

  • GC impredecible . Ajustar lo que stepdebería ser cambia drásticamente por juego. Algunos funcionan mejor con GC completo en cada cuadro (conjunto de trabajo pequeño). Algunos funcionan mejor con pases mucho más pequeños con menos frecuencia. Tenga en cuenta que hay mucho trabajo para mejorar el GC en las nuevas versiones de lua y en algunos parches (¡que no debe tener miedo de usar!)
  • mayor sobrecarga . Mantenemos muchas de nuestras grandes estructuras de datos en el lado C para evitar sobrecarga de memoria por entrada de tabla. C ++, C y ensamblaje generalmente producen código más rápido. Por lo tanto, se mantiene en el 90% del motor del juego que no es crítico para el rendimiento, y ocasionalmente migramos cosas de lua a C (o viceversa).
  • la fragmentación . Quizás el mayor problema en sistemas de memoria pequeña. Usualmente usamos grupos de objetos pequeños y un montón de objetos grandes completamente separado para lua. Ponemos pases completos de GC en puntos estratégicos del juego. Descargamos scripts o los descartamos por lua_Statecompleto en algunos casos. Y todavía a veces tenemos problemas. Ajustar los tamaños de los grupos de objetos pequeños (son fijos, por simplicidad y menor sobrecarga) y el tamaño del montón de objetos grandes específicos de lua puede ser una molestia. Pero en sistemas de más de 4 MB, todavía no nos hemos molestado con los montones y grupos especializados.
  • falta de seguridad de tipo . Si no tiene un buen conjunto de herramientas de análisis de código estático incorporado, recurrirá a una gran cantidad de verificación de errores de tiempo de ejecución (tal vez usando __indexy __newindex). Es mejor si puede detectar errores en tiempo de compilación. Hay varias cosas que puede hacer para aliviar esto.

Lua es muy recomendable, ¡solo esté dispuesto a trabajar un poco! También es posible que desee consultar Squirrel , aunque creo que tiene una base de usuarios más pequeña.

leander
fuente
Desearía poder votar esto varias veces. Muy completo, muy perspicaz, claramente estructurado. +1
Koarl
5

En realidad, hay 3 grandes ventajas:

Estos factores te permiten, como desarrollador de juegos, habilitar funciones que acelerarán el desarrollo y aumentarán la calidad de tu juego.

Por ejemplo:

  • Podrás cambiar la lógica de tu juego simplemente actualizando tu juego desde un archivo o un socket de red.
  • Puede permitir que los usuarios creen sus propios scripts (para bots o mods)
  • Sus diseñadores y artistas del juego podrán actualizar y probar partes del juego sin tener que usar su conjunto de herramientas de compilación.
  • No tendrá que volver a compilar cada vez que cambie algunos scripts.
  • No tendrás que reescribir todo el juego si cambias de plataforma / motor / idioma.
Coyote
fuente
1
"No tendrás que reescribir todo el juego si cambias de plataforma / motor / idioma". A menos que cambie de Lua a otro idioma. Y si estás escribiendo tu "juego completo" en Lua, si cambias de motor, entonces ese cambio tiene que estar expuesto a Lua (o necesitas algo de abstracción entre Lua y el motor para ocultar los detalles). Así que no veo cómo Lua ayuda en esos casos.
Nicol Bolas
3

Desde mi experiencia, se redujo un poco.

Pros

  • La integración inicial es realmente fácil. Existen herramientas para ayudar a generar enlaces, pero el mecanismo de enlace es tan simple que podría escribir su propia versión del mismo, con sus propias características personalizadas, en poco tiempo
  • Obtiene una iteración mucho más rápida en la lógica del juego (suponiendo que implemente la recarga en tiempo de ejecución)
  • Obtendrá un entorno liberador para experimentar: probará más cosas porque la sobrecarga para hacerlo disminuye significativamente
  • Sintaxis familiar: a pesar de todas sus diferencias, como programador en C sería muy difícil no sentirse cómodo en cuestión de horas
  • Mejor separación de la lógica del juego con el "motor": su motor se convierte en un proveedor de servicios que tiene que exponer una API decente al cliente Lua. La barrera del idioma te hace pensar más en eso, en lugar de solo buscar y manipular una variable miembro

Contras

  • La gestión de la memoria Lua no es ideal para juegos. Lo enfrentas, no te gusta
  • La depuración de Lua es horrible fuera de la caja. Tendrás que trabajar para mejorar la experiencia.
  • Mantener los datos en Lua significa que deberá depurar en Lua: inspeccionarlos desde C inicialmente será complicado
  • Lua tiene una buena cantidad de disparos en la sintaxis del pie, ya que todas las variables son globales de forma predeterminada
  • Lua es un lenguaje de programación, como cualquier otro. No espere que los no programadores se conviertan mágicamente en programadores solo porque eliminó el compilador
  • Mejorar la integración y el soporte de Lua es una gran parte del trabajo. No esperes que ronronee desde el primer momento. Es justo suponer que realmente tendrá que amortizar este costo en unos pocos juegos

Veredicto final, personal: si estás creando un juego de tamaño decente y aún no tienes un lenguaje de script, entonces obtén Lua. Valdrá la pena.

Chris Subagio
fuente
1

Garry's Mod es un ejemplo de un juego que usa Lua y C ++. Usan Lua para todos los mods, lo que los hace mucho más fáciles de hacer para las personas. C ++ se usa para todas las partes internas. El único inconveniente que se me ocurre es que Lua no es tan rápido como C ++.

TheGag96
fuente