29 pontos por GN⁺ 2024-04-27 | 13 comentários | Compartilhar no WhatsApp
  • Sobre a alegação de que todos os problemas desaparecem quando você se acostuma com Rust
    • Mesmo se acostumando com Rust, os problemas fundamentais não desaparecem
    • Jogos são máquinas de estado complexas e, como os requisitos mudam o tempo todo, isso não combina com a natureza estática e excessivamente verificadora do Rust
    • O problema de precisar refatorar o código o tempo todo é autoinfligido
  • Problemas de grandes refatorações causados pelo borrow checker
    • Rust força refatorações com mais frequência do que outras linguagens
    • Em situações em que os requisitos do jogo mudam com frequência, você acaba brigando com o borrow checker e precisa reestruturar o código
    • É difícil concordar com a ideia de que refatoração gera código bom. Código bom surge ao iterar sobre ideias e testá-las
  • A indireção resolve apenas alguns problemas e reduz a produtividade no desenvolvimento
    • Ao usar indireção para resolver problemas do borrow checker, a lógica do código fica separada e mais complexa
    • Em jogos, há eventos conectados, timing específico e muito gerenciamento de estado, e a indireção torna isso mais difícil
    • Em Rust, até código simples precisa ser escrito de forma verbosa por causa da indireção
  • ECS (Entity-Component-System) resolve o problema errado
    • As vantagens do ECS são, na verdade, vantagens da generational arena
    • O ECS é visto sob várias perspectivas: composição dinâmica, structure of arrays, solução para o borrow checker do Rust, generational arenas criadas dinamicamente etc.
    • Mas é questionável se ECS é realmente a abordagem mais adequada para desenvolvimento de jogos. Mais importante do que performance ou composição é focar na lógica do jogo
  • Sistemas generalizados não levam a uma jogabilidade divertida
    • Usar sistemas generalizados demais acaba gerando uma jogabilidade sem graça
    • Bons jogos exigem projetar cuidadosamente interações detalhadas, sincronizar VFX, repetir playtests e experimentos e lançar rápido para receber feedback
    • Rust persegue valores que não são adequados para prototipagem rápida e iteração
  • No desenvolvimento de jogos, o importante é prototipar e iterar rapidamente, mas os valores do Rust vão na direção oposta
    • O essencial no desenvolvimento de jogos é o jogo em si e a experiência do jogador, não código sem crashes
    • A manutenibilidade do código de jogo não é um valor tão importante em jogos indie. O que importa é a velocidade de iteração
    • Rust está tão obcecado em evitar problemas que acaba deixando de lado o que realmente importa
  • Procedural macros ficam muito aquém de reflection
    • No desenvolvimento de jogos, é preciso escrever código para sistemas, gameplay, UI, VFX, áudio, ferramentas e várias outras áreas
    • Em Rust, até algo simples como "imprimir um objeto" exige escrever código manualmente ou criar procedural macros
    • Procedural macros são muito mais limitadas que macros declarativas e também aumentam bastante o tempo de compilação
    • Reflection em C# é muito mais fácil de usar e permite desenvolver rapidamente quando performance não é crítica
  • Hot reloading tem papel importante no aumento da velocidade de iteração
    • Hot reloading é muito útil para UI/desenho em modo imediato, depuração e ajuste fino de constantes de gameplay
    • Rust também tem hot-lib-reloader, mas ele não é perfeito e exige planejamento e antecipação, o que limita usos mais criativos
    • Desenvolvedores de jogos querem ferramentas de nível mais alto do que simples recarregamento de struct
  • Abstração não é opcional, é obrigatória
    • Exemplo real) Quando é preciso ter comportamentos diferentes conforme o estado da UI, em Rust acaba sendo necessário refatorar ou abusar de clones
    • Muitas vezes o código é alterado não porque a lógica de negócio mudou, mas para satisfazer o compilador
    • Rust não tem um sistema de tipos estruturais como "um tipo com estes campos", então ao refatorar é preciso modificar vários trechos do código
  • A situação de GUI em Rust é péssima
    • O importante em UI de jogos não é data binding nem atualizações reativas, e sim personalizar a aparência
    • O que a UI de jogos precisa é de GUI bonita, sprites customizados, animações, vector shapes, partículas, efeitos, flashes etc.
    • Atualmente não existe uma biblioteca Rust especializada em GUI para jogos
  • A orphan rule deveria ser opcional
    • A orphan rule reduz muito a produtividade de desenvolvimento em nome da segurança
    • Em código de aplicação, e não de biblioteca, deveria ser possível desativar a orphan rule
  • O tempo de compilação melhorou, mas ainda é lento quando se usam proc macros
    • Proc macros como serde aumentam muito o tempo de compilação
    • Em builds incrementais que levam mais de 20 a 30 segundos, ajustar detalhes finos fica muito difícil
  • O ecossistema de desenvolvimento de jogos em Rust parece supervalorizado
    • Não há tantas pessoas realmente criando jogos
    • Muitos projetos com sites ou READMEs chamativos e aparência famosa, na prática, não são tudo isso
    • Se você quer realmente fazer jogos, a recomendação é godot-rust. Em vez de insistir em uma solução puramente em Rust, é melhor contar com a ajuda de um engine maduro
  • Como jogos são single-threaded, a justificativa para o incômodo com estado global está errada
    • Em Rust, usar estado global é muito incômodo (static mut, AtomicRefCell, Rc etc.)
    • Mas, diferentemente de serviços backend, jogos costumam ser single-threaded, então esse nível de incômodo não seria necessário
    • O autor considera que foi um erro o Bevy introduzir sistemas paralelos. Foi feito por performance, mas acabou só aumentando a inconveniência, exigindo que o usuário especifique ordem o tempo todo
  • Dynamic borrow checking causa crashes inesperados após refatorações
    • Ao usar hecs por 2 anos, o autor viu com frequência casos em que queries se sobrepunham e causavam crashes
    • O mesmo ocorre com RefCell: se .borrow_mut() é chamado em dois lugares, acontecem crashes inesperados
    • Não é tanto que o código seja ruim, e sim que Rust força refatorações desnecessárias
    • RefCell é útil em jogos, mas Rust torna seu uso difícil demais
  • Falta flexibilidade aos objetos de contexto
    • Como em Rust é difícil usar estado global, usa-se o padrão de reunir referências em um objeto de contexto e passá-lo adiante
    • Mas, ao emprestar apenas alguns campos, surgem erros de compilação por causa de partial borrow
    • Dizem para quebrar o Context em partes e mudar a estrutura, mas o que se quer fazer é lógica de jogo; mudar a estrutura apenas para satisfazer o compilador é perda de tempo

Vantagens do Rust

  • Quando compila, normalmente funciona bem. É especialmente útil para ferramentas CLI, processamento de dados e escrita de algoritmos
  • Entrega boa performance sem grande esforço. O autor relata experiência de ser cerca de 1,5 a 2,5 vezes mais rápido que C#
  • enum é muito bem implementado
  • A usabilidade de IDE melhorou bastante graças ao Rust analyzer
  • O sistema de trait é bom. Se a orphan rule fosse um pouco mais flexível, seria ainda mais útil

Opinião do GN⁺

  • Embora a visão sobre Rust seja em geral negativa, parece importante levá-la a sério, já que é uma conclusão a que o autor chegou após diversas tentativas. Especialmente no domínio de desenvolvimento de jogos, faz sentido a observação de que praticidade e velocidade de desenvolvimento são muito importantes, e que o Rust ainda deixa a desejar nesses pontos.

  • Concordo que a segurança buscada pelo Rust às vezes pode reduzir severamente a produtividade. Ao escrever código em Rust, muitas vezes se gasta mais tempo tentando satisfazer o compilador do que trabalhando na própria lógica, e isso parece vir do fato de Rust ser, no fundo, uma linguagem especializada em programação de sistemas

  • Por outro lado, desenvolvimento de jogos costuma acontecer em ambientes single-threaded, onde prototipagem rápida e iteração são fundamentais, então verificações de segurança excessivas podem acabar sendo mais prejudiciais do que úteis. Especialmente no início do Rust, muita gente tentou fazer jogos com a linguagem e acabou frustrada; pelo visto, esses problemas fundamentais ainda não melhoraram tanto.

  • É verdade que engines de jogo mais recentes, como Bevy, melhoraram a conveniência do desenvolvimento de jogos em Rust, mas ainda parecem muito distantes do nível de engines maduras como Unity ou Godot. Como o texto sugere, em vez de construir tudo de forma puramente em Rust, usar Rust junto com engines existentes pode ser uma alternativa mais realista

  • As vantagens mencionadas pelo autor ficam muito mais evidentes quando se usa Rust em áreas fora dos jogos. Em domínios como programação de sistemas ou desenvolvimento de servidores web, a segurança e a alta performance do Rust são grandes trunfos, mas esses benefícios não parecem ter tanto peso assim no desenvolvimento de jogos

  • No fim das contas, Rust não é uma linguagem universal, e sim uma linguagem especializada em certos domínios, então vale considerar com cuidado se ela realmente combina com a natureza do seu projeto

13 comentários

 
coremaker 2024-04-29

Acho que rust é uma linguagem pensada para resolver problemas causados por diversos tipos de falhas de desenvolvedores, numa realidade em que há cada vez menos desenvolvedores capazes de escrever código íntegro no nível do core.

Como ela é mais adequada para desenvolver com precisão do que com rapidez,
não é apropriada para projetos em que requisitos adicionais dos usuários surgem com frequência e precisam ser executados.

Mesmo assim, acho que o desejo pelo surgimento de uma biblioteca de UI
vem da expectativa de que, mesmo com uma UI pequena e simples funcionando sobre um código robusto, sua utilidade melhoraria bastante.

 
kandk 2024-04-29

Como nunca desenvolvi jogos, não sei ao certo,
mas parece que escolheram a linguagem errada desde o começo, ou, se a velocidade de iteração no desenvolvimento era importante, deveriam ter escolhido uma linguagem de nível script...
ou então faltou uma compreensão mais profunda do sistema.
Acho que, mesmo se tivessem escolhido C++, teriam enfrentado problemas parecidos.

 
cosine20 2024-04-29

Isso mesmo. Bem, se eu tivesse escolhido C++, haveria a opção da Unreal, é claro...

 
cosine20 2024-04-29

Hoje em dia, tenho a impressão de que linguagens nativas como Rust e C++ parecem mais adequadas para o desenvolvimento de middleware, como engines de jogo, do que para o desenvolvimento de clientes de jogos.
Assim como quase não há casos de desenvolvimento web full stack com linguagens nativas.

 
kandk 2024-04-29

Desde o início, era uma linguagem feita para esse propósito. Como substituta do C++.
Acho que o texto acabou virando mais uma crítica à linguagem.

 
cosine20 2024-04-29

Isso mesmo. Acho que originalmente começou para melhorar o motor interno do Firefox?
Pela vibe do texto, parece aquele caso de tentar desenvolver com Rust em uma área que não combina muito bem com a linguagem, como se fosse uma panaceia, e acabar sofrendo por isso kkk

 
mammal 2024-04-29

Concordo 100%. Para a lógica de jogos, uma linguagem com boa produtividade parece mais adequada ao caso de uso.

 
edunga1 2024-04-28

Estou começando com Rust, então consigo me identificar um pouco.
É doloroso ter que modificar código demais por causa de mudanças no borrowing.
Diferente de Python e JavaScript, que têm muitas expressões implícitas, Rust tende a ser explícito, então às vezes o código fica verboso e, como obriga o programador a fazer muitas escolhas, também pode ser cansativo.
Mesmo assim, os conceitos que não existem em outras linguagens são novos e divertidos.

Se não fosse pelo Rust Analyzer e pelo GitHub Copilot, acho que eu teria desistido bem antes.

 
botplaysdice 2024-04-28

Como era de se esperar, desenvolvimento de jogos é hardcore mesmo...

 
steamb23 2024-04-28

Em vez de fazer tudo em Rust, do core ao front-end,
que tal escrever o core em Rust, como no Unity ou em outras engines de jogo, e usar em conjunto uma linguagem mais produtiva?

 
bus710 2024-04-28

Acho que não tem muito como evitar, já que ele tende a impor a estrutura de forma bem rígida.

 
[Este comentário foi ocultado.]
 
GN⁺ 2024-04-27
Comentários do Hacker News

Compartilha a experiência de desenvolver um cliente de metaverso e aponta problemas do Rust

  • Quase não há casos de desenvolvimento de jogos 3D de grande porte com Rust
  • Refatorar e conectar as diferentes partes do programa é doloroso
  • A renderização é quase adequada, mas a stack não está completa nem é confiável
  • Os sistemas de GUI 2D são fracos e exigem código demais para cada caixa de diálogo
  • Concorda com o problema de o sistema async se espalhar até para áreas desnecessárias

Como desenvolvedor de jogos com 20 anos de experiência, considera que Rust não é adequado para desenvolvimento de jogos

  • O código de gameplay precisa ser flexível e ter muitos edge cases para criar jogos interessantes
  • O tempo de compilação importa, e mudanças estruturais são frequentes
  • ECS é útil para alguns sistemas, mas é difícil de usar em código de gameplay ou de UI

O ecossistema de desenvolvimento de jogos em Rust depende de hype exagerado

  • Tentou desenvolver jogos com Rust, mas teve uma experiência terrível imediatamente
  • Tempo de compilação lento, downloads enormes de pacotes e a dificuldade do próprio Rust
  • Dizem que outras ferramentas não são tão seguras quanto Rust, mas raramente a segurança de memória foi um grande problema em jogos

Compara a experiência de desenvolvimento de jogos com Bevy, Unity e Godot

  • Hoje é difícil entender por que escolher Rust para desenvolvimento de jogos
  • Enfiar tudo em ECS atrapalha o desenvolvimento de gameplays divertidos
  • Considerando o desempenho dos PCs modernos, não há necessidade de se preocupar tanto com otimizações de multithreading

A linguagem Nim pode ser mais adequada para desenvolvimento de jogos do que Rust

  • Dá suporte a hot reloading sem atrapalhar o desenvolvedor

Rust parece uma linguagem dogmática que força uma forma específica de programar

  • Coloca a segurança de memória acima de tudo, mas isso não é tão útil em desenvolvimento de jogos
  • A linguagem ideal para desenvolvimento de jogos deveria ter alta produtividade, desempenho adequado e ser voltada a programadores experientes que sabem assumir riscos

A demo de tooling de Allen Blomquist mostra que o loop de feedback no desenvolvimento é importante

  • Como Rust não oferece o ambiente de trabalho desejado, voltou para Unity

O problema fundamental do Rust é abandonar orientação a objetos e preferir programação funcional

  • Isso pode ajudar no núcleo de mais baixo nível, mas não é adequado em níveis mais altos

Em desenvolvimento de jogos, Rust é a pior escolha

  • Os valores do Rust, que buscam precisão, segurança e código perfeito, não combinam com desenvolvimento de jogos
  • Jogos têm vida útil curta e ciclos de desenvolvimento curtos, então a qualidade do código não é tão importante
  • Pode ajudar no desenvolvimento de engines, mas deve ser usado junto com uma linguagem de script altamente flexível

Ao programar em D, percebeu que é muito mais fácil mudar o layout dos dados do que em C

  • Alternar entre tipos por referência e tipos por valor é difícil em C, mas fácil em D