Quais são os prós e os contras de incorporar Lua em um jogo em C ++?

37

Eu tenho um livro de programação de jogos em C ++ e ele possui uma seção Lua. Comecei a ler a seção Lua, e isso parece interessante, mas não consigo determinar os prós e os contras do uso de Lua no meu jogo em C ++. O único benefício que posso pensar atualmente é que você pode fazer algumas atualizações de codificação, via Lua, sem precisar recompilar. Fora isso, não consigo pensar em nada. Então, quais são os prós e os contras de adicionar Lua a um jogo em C ++?

Exemplos seriam apreciados.

Ryan
fonte
Concorde que é semelhante a essas perguntas, mas o importante aqui são os "contras".
Jonathan Dickinson
@ JonathanDickinson, as respostas não apontam para essa direção ... elas basicamente afirmam o mesmo que na pergunta vinculada.
bummzack

Respostas:

33

O único benefício que posso pensar atualmente é que você pode fazer algumas atualizações de codificação, via Lua, sem precisar recompilar.

Não descarte a utilidade disso tão facilmente. Você nunca entenderá o quão produtivo será até retirar a etapa de recompilação.

O "fluxo" é um conceito psicológico bastante bem compreendido quando se trata de trabalho. O fluxo é aquele sentimento que você sente quando se concentra em uma atividade, quando está analisando e resolvendo problemas quase sem pensar, etc. Você está mais produtivo quando está "fluindo".

Os tempos de compilação estragam tudo isso. É difícil permanecer no fluxo se você tiver uma compilação de 10 segundos entre testar algo.

Quando você está desenvolvendo uma jogabilidade, o que você costuma ter é um "loop apertado". Você tem uma ideia, codifica um teste para ver se funciona e depois tenta. Se não funcionar, modifique-o e tente novamente. O tempo de "código para teste" é muito importante para manter o fluxo. Obter o menor tamanho possível é crucial.

O que Lua (ou qualquer linguagem de script incorporada) permite que você faça é testar as alterações, não apenas sem "compilar", mas viver no jogo . Dependendo de como você constrói seu jogo, você pode executar um comando que reiniciará o jogo com novos scripts sem precisar parar e recarregar dados e assim por diante. Além de não precisar recompilar, você não precisa executar novamente.

A capacidade de fazer isso, com o suporte adequado do mecanismo, pode aumentar drasticamente a produtividade.


Outro grande benefício do script é a capacidade de não se importar. Se você passou muito tempo escrevendo C ++, ficaria surpreso com quanto tempo gasta em minutos. Onde a memória é apagada. Onde isso é liberado. Mesmo se você estiver usando em shared_ptrqualquer lugar, apenas o ato de digitar todos esses nomes de tipos de variáveis ​​atrasará você.

Em uma linguagem de script de tipo dinâmico, você não precisa se preocupar. O escopo é simples. Funções são objetos de primeira classe; você não precisa criar functors manualmente. É tão fácil fazer algumas coisas.

Agora isso tem negativos, se você não é um programador disciplinado. É muito fácil usar globais em Lua (embora haja maneiras de evitar isso). Não se importar significa que você pode ser muito desleixado ao codificar.

Mas, novamente, ser muito desleixado pode ter vantagens .


Outra vantagem do Lua é que ele cria uma boa linguagem de descrição de dados. Assim como o JSON é apenas um arquivo JavaScript que cria e retorna uma matriz / tabela, você pode criar scripts Lua que retornam tabelas.

Isso é útil para arquivos de configuração; O formato da tabela de Lua é muito melhor que o formato .ini. O formato ainda é bastante limpo, compacto e extensível.

Ah, e ainda é um script Lua, para que ele possa executar a lógica real. A desvantagem disso é ... bem, é um script Lua, para que ele possa executar a lógica real . Isso pode ser desastroso no jogo, já que o usuário pode começar a estragar tudo.

Mas, na verdade, isso é facilmente resolvido. Lua foi projetado para incorporação, o que significa que o isolamento é realmente muito fácil. De fato, um novo estado Lua não fornece nada por padrão; você realmente precisa fazer algo para expor até mesmo as bibliotecas Lua mais básicas. O acesso a arquivos, o estado do jogo, etc., é opcional, não opcional. E cada estado Lua é separado um do outro. O estado Lua que você usa para scripts AI não precisa ser o estado Lua usado para arquivos de configuração.

Na verdade, eu tenho um código que permite registrar muitas bibliotecas padrão Lua, mas analisa e remove todas as E / S de arquivos. Por fim, o pior que um arquivo de configuração baseado em script Lua poderia fazer é causar o travamento do seu jogo imediatamente após a execução, ficando sem memória. E como você não está compartilhando esses arquivos de configuração manualmente, isso não seria muito divertido para um hacker.


Eu diria que a maior desvantagem de qualquer linguagem de script é a depuração. A maioria das linguagens de script não possui depuradores, e Lua não é diferente. Lua possui todas as ferramentas necessárias para criar ferramentas de depuração. Mas, na verdade, ele não possui um depurador embutido. Você tem que montar um. E isso exigirá um grau razoável de trabalho.

Ou você pode fazer o devido com "printf debugging". Realmente depende de quanto código Lua você escreve.

Nicol Bolas
fonte
11
fluir nem sempre é uma coisa boa; fazer as coisas automaticamente às vezes significa não demorar para analisar alternativas de design.
lurscher 9/10/11
10
@ lurscher: Design é o que você faz antes de se sentar para codificar. Você deveria ter elaborado todas essas alternativas de design antes de começar a escrever, testar e depurar seu código.
Nicol Bolas
23

Onde eu trabalho:

Prós:

  • tempo de iteraçãomelhorias no . Nosso jogo é configurado para pesquisar mudanças no sistema de arquivos do host e automaticamente "engolir" as alterações. (Eles só entram em vigor no próximo arquivo aberto, mas, na prática, isso é uma grande melhoria: recarregue o nível e suas novas alterações lua aparecerão imediatamente.)
  • integração de console . Qualquer funcionalidade de depuração pode ser conectada a um console tradicional no estilo Quake com um REPL. Para compilações internas, podemos até conectar um lua REPL a um soquete simples que fala telnet e temos controle de rede sobre o nosso jogo.
  • API reduzida e menor curva de aprendizado . Artistas e designers não técnicos podem participar de algumas tarefas que normalmente seriam prejudicadas pelo programador.
  • análise de código estático especializado . É fácil analisar a saída luac -le espiar o bytecode para fazer algumas análises; também é muito fácil analisar a maioria dos arquivos de origem lua, especialmente se você tiver uma convenção de codificação. Podemos aplicar a convenção local. Você também pode procurar no metalua ainda mais energia aqui.
  • tratamento de erros . Se nossa API estiver livre de falhas, mesmo que lua faça algo bobo, podemos capturá-la e recuperar usando lua_pcall.
  • extensão de API fácil . Escrever uma nova função para a API Lua <-> C ++ não é muito difícil. Existem também pacotes que ajudarão a automatizar isso.
  • fonte simples . Fazer alterações para, por exemplo, evitar matemática de ponto flutuante no interpretador lua (importante em algumas plataformas incorporadas) ou otimizar para sistemas específicos não é muito difícil!
  • meta-tabelas . Estes são impressionantes. Muito potencial para fazer coisas interessantes em tempo de execução. Temos "tabelas virtuais" que na verdade não têm conteúdo e realizam uma pesquisa em uma estrutura de dados complicada no lado C ++ de nossos jogos.
  • corotinas . Ser capaz de parar e retomar, por exemplo, scripts de comportamento de IA é incrível. No entanto, é um pouco mais inteligente por parte dos roteiristas da lua - ainda estamos trabalhando em como tornar isso mais "seguro" com nosso mecanismo.

Contras:

  • GC imprevisível . Ajustar o que stepdeveria ser muda drasticamente por jogo. Alguns funcionam melhor com o GC completo em todos os quadros (pequeno conjunto de trabalho). Alguns funcionam melhor com passes muito menores com menos frequência. Observe que há muito trabalho para melhorar o GC nas versões mais recentes da lua e em alguns patches (que você não deve ter medo de usar!)
  • maior sobrecarga . Mantemos muitas de nossas grandes estruturas de dados no lado C para evitar sobrecarga de memória por entrada na tabela. C ++, C e assembly geralmente produzem código mais rápido. Portanto, ele mantém os 90% do mecanismo de jogo que não são críticos para o desempenho e, ocasionalmente, migramos coisas de lua para C (ou vice-versa).
  • fragmentação . Talvez o maior problema em sistemas de memória pequena. Geralmente usamos pequenos pools de objetos e um heap de objetos grandes completamente separado para lua. Colocamos passes completos do GC em pontos estratégicos do jogo. Nós descarregamos scripts ou descartamos lua_Statecompletamente em alguns casos. E às vezes ainda temos problemas. Ajustar os tamanhos dos pequenos pools de objetos (eles são fixos, para simplificar e reduzir a sobrecarga) e o tamanho da pilha de objetos grandes específicos da lua pode ser um problema. Mas em sistemas maiores que cerca de 4 MB, ainda não nos preocupamos com as pilhas e os pools especializados.
  • falta de segurança do tipo . Se você não tiver um bom conjunto de ferramentas de análise de código estático, poderá recorrer a muitas verificações de erros em tempo de execução (talvez usando __indexe __newindex). É melhor se você conseguir detectar erros em tempo de compilação. Existem várias coisas que você pode fazer para aliviar isso.

Lua é altamente recomendado, apenas esteja disposto a trabalhar um pouco! Você também pode conferir o Squirrel , embora eu acredite que ele tenha uma base de usuários menor.

leander
fonte
Eu gostaria de poder votar isso várias vezes. Muito abrangente, muito perspicaz, claramente estruturado. 1
Koarl 21/03
5

Na verdade, existem 3 grandes vantagens:

Esses fatores permitem que você, como desenvolvedor de jogos, habilite recursos que irão acelerar o desenvolvimento e aumentar a qualidade do seu jogo.

Por exemplo:

  • Você poderá alterar a lógica do jogo simplesmente atualizando o jogo a partir de um arquivo ou soquete de rede.
  • Você pode permitir que os usuários criem seus próprios scripts (para bots ou mods)
  • Seus designers e artistas de jogos poderão atualizar e testar partes do jogo sem precisar usar seu conjunto de ferramentas de compilação.
  • Você não precisará recompilar toda vez que alterar alguns scripts.
  • Você não precisará reescrever o jogo inteiro se mudar de plataforma / mecanismo / idioma.
Coiote
fonte
11
"Você não terá que reescrever o jogo inteiro se mudar de plataforma / mecanismo / idioma." A menos que você mude de Lua para outro idioma. E se você estiver escrevendo seu "jogo inteiro" em Lua, se alterar os mecanismos, essa alteração deverá ser exposta a Lua (ou você precisará de alguma abstração entre Lua e o mecanismo para ocultar os detalhes). Portanto, não vejo como Lua ajuda nesses casos.
Nicol Bolas
3

Da minha experiência, resumiu-se um pouco.

Prós

  • A integração inicial é realmente fácil. Existem ferramentas para ajudar a gerar ligações, mas o mecanismo de ligação é tão simples que você pode escrever sua própria versão, com seus próprios recursos personalizados, em pouco tempo
  • Você obtém uma iteração muito mais rápida na lógica do jogo (supondo que você implemente o recarregamento do tempo de execução)
  • Você terá um ambiente libertador para experimentar: experimentará mais coisas, porque a sobrecarga para fazer isso cai significativamente
  • Sintaxe familiar: apesar de todas as suas diferenças, você seria pressionado como programador C para não se sentir confortável em poucas horas
  • Melhor separação da lógica do jogo com o "mecanismo": seu mecanismo se torna um provedor de serviços que precisa expor uma API decente ao cliente Lua. A barreira do idioma faz você pensar mais sobre isso, em vez de apenas chegar lá e mexer com uma variável de membro

Contras

  • O gerenciamento de memória Lua não é ideal para jogos. Você lida com isso, você não gosta
  • A depuração de Lua é horrível fora da caixa. Você terá que trabalhar para melhorar a experiência
  • Manter dados em Lua significa que você precisará depurar em Lua: inspecioná-los a partir de C será inicialmente complicado
  • Lua tem uma boa quantidade de tiros na sintaxe do pé, como todas as variáveis ​​sendo globais por padrão
  • Lua é uma linguagem de programação, como qualquer outra. Não espere que não programadores se transformem magicamente em programadores apenas porque você removeu o compilador
  • Ficar bom em integrar e dar suporte a Lua é um grande pedaço de trabalho. Não espere que ele ronronar imediatamente. É justo supor que você realmente precisará amortizar esse custo em alguns jogos

Final, pessoal, veredicto: se você está construindo um jogo de tamanho decente e ainda não possui uma linguagem de script, obtenha Lua. Vai valer a pena.

Chris Subagio
fonte
1

O Mod de Garry é um exemplo de jogo que usa Lua e C ++. Eles usam Lua para todos os mods, o que os torna muito mais fáceis para as pessoas. C ++ é usado para todos os internos. O único engodo que consigo pensar seria o fato de Lua não ser tão rápida quanto C ++.

TheGag96
fonte