sábado, 14 de abril de 2018

Problemas crônicos do jogo: a precisão dos números float na Unity

Um comentário do João Victor Lucas no grupo do Proton no Facebook me chamou a atenção, por questionar algo que pouca gente observou. Vamos lá:

Esses bugs persistem desde umas versões mais antigas do jogo. Talvez não dê para alterar tudo agora, mas se for possível, agradeço.

Mi2M continua com o pontilhado no lado direito do parabrisa, perto da divisória.


As manchas vermelhas e verdes no modelo do Mi2M reduziram drasticamente, embora persista algum ranço verde na tampa interna do itinerário e nos pneus. Um detalhe curioso é que quanto mais qualidade eu ponho nas configurações, mais essas manchas reduzem e vice-versa.


O Invisibus está com controles estranhos, tem chaves de manual e botões de automático misturados. E não mostra a velocidade dele quando se desloca.


O N do câmbio manual funciona mesmo, pois o veículo segue numa velocidade constante. Já o N do automático faz o veículo reduzir a velocidade e parar num ritmo bem lento (não sei se na vida real é assim, mas enfim).


Na câmera interna traseira do MiBRTS, quando dou a volta usando as setas, ela "atravessa" um pedaço da carroceria... Tá, eu sei que o carro tem balanço traseiro curto, mas os outros Mis do jogo também têm, nem por isso acontece com eles.


Minha resposta:

---------

Algumas das coisas citadas são meio crônicas, de difícil solução... Teremos que conviver com elas por um bom tempo. São coisas pertinentes que acho que não comentei amplamente ainda, vamos lá:

Trechos verde ou rosa no Mi2M


Isso ocorre mais ao jogar com qualidade baixa. A textura é menor nesse modo, os quadros das cores pintados nele ficam mais próximos e a GPU perde precisão na seleção, assim acaba pegando as bordas do quadro ao lado. Ele usa uma textura cheia de quadrinhos com cores, quanto menor a qualidade, menores eles ficam, ficando bem apertados... Fiz um experimento nele usando uma textura só para todo o interior exceto as coisas que acendem, o resultado não foi tão bom quanto o esperado, provavelmente é algo que não vou repetir nos demais (usar poucas texturas sim, sempre é bom, mas sem a intenção de usar uma só para todo o interior).



Invisbus problemático


O invisbus acabou não recebendo algumas alterações dos demais (não testei mais), provavelmente ele será removido. Usava ele para testar o desempenho do jogo quando não tinha certeza sobre até que ponto posso ou não detalhar os demais. Mas já tiramos conclusões, os outros detalhados funcionam bem na maioria dos aparelhos, já deu para ter uma base.

O neutro não funciona como deveria


O câmbio manual usa um código bem complexo, ele é mais realista em vários sentidos, ainda que algumas coisas não estejam bem ajustadas porque não entendi (caso da embreagem). O automático é bem simples, fica mais tipo um arcade ou GTA, o neutro nele se tornou apenas uma forma de não ir pra frente nem dar ré. Não é e nem tem como ser tão realista. Futuramente usarei algum outro código para os automáticos.

A câmera não mostra as coisas próximas / fica vazada ao girar



E o problema da câmera interna ao girar... Esse é um que quase me fez desistir do jogo há uns anos.

É porque a distância mínima de renderização da câmera está configurada em 0.3 metros (ela não pega nada mais perto do que 30cm). Isso é uma eterna encrenca com mapas grandes na Unity, por conta da precisão dos números que ela usa para os posicionamentos dos objetos... Quero fazer mapas para percorrer vários km e a engine não oferece um meio nativo para isso. Se a distância da câmera for menor que 30cm a perda da precisão dos números quando está longe (depois de ter andado bastante) faz com que a câmera fique piscando, as sombras, luzes e tudo fora de lugar... Isso é perceptível ao ficar dirigindo sem parar, dá pra ver bem na rodovia, depois de 10km percorridos as coisas ficam tremendo. Ao parar o ônibus ele move tudo pro ponto central e o problema é "corrigido" (até os próximos 10km). Se eu deixar a distância da câmera menor (10cm ou menos, como seria o ideal) as piscadas começam a acontecer muito mais cedo, logo depois de 1km, em vez de 10. Isso acontece porque ela usa apenas sete dígitos para guardar as posições dos objetos, movendo a vírgula entre os 7 dígitos. Ao passar de 1km ou seja 1000 unidades, ficam 3 casas decimais (dá para ter uma precisão de milímetros). Ao passar de 10km, ou 10.000 metros, sobram só duas casas decimais. Aí a coisa fica feia, o jogo fica com precisão nos centímetros, coisas muito próximas e pequenas ficam tremendo, fora de lugar, a sombra pisca também etc. A solução "gambiarra" encontrada foi mover tudo para o ponto 0,0,0 quando o jogador passa de algumas centenas de metros, antes de chegar a 1km. Mas se faço isso com o ônibus em movimento ele girava e saía do controle, zoando toda a física... Então configurei para mover e resetar a origem só ao parar. É naquela hora que o GPS dá uma "bugada" (ele move tudo, o GPS mostra a posição anterior e é refeito).

Essa limitação da Unity por várias vezes quase me fez desistir do jogo, mas decidi encarar assim mesmo, sofrendo as consequências (tendo que ter essa distância grande na câmera e mover o jogador para o 0,0,0 quando ele passar de 999 metros). Por isso outros games sofrem também, caso do HBS/HTS que param tudo pra carregar cenário (além do peso de ter tudo carregado de uma vez, tem o problema da precisão dos números float). Eu não quis fazer mapas pequenos com pausas para carregar, decidi encarar um mapa grande mesmo com esses contratempos.

Se eu aumentar a distância mínima da câmera para 1m a coisa melhora de um lado na questão do mapa grande (não precisaria mover a cada 10km, mas sim a cada 100)... Mas prum jogo de direção com câmera interna não dá pra manter a câmera renderizando só de um metro pra frente de onde está o jogador, iria pular muita coisa.

É um tema complexo, não sei se deu pra entender rs mas se tiver interesse pesquise por floating point precision na Unity ou em games em geral.

Para fins de testes internos, aquele DO que aparece nas mensagens ao mostrar os fps é a distância da origem, a distância da câmera ao ponto 0,0,0. Quando ela passa de 999 fica com 3 casas decimais, aí começa a tremedeira. Aí ao parar move tudo pro 0,0,0 (dá um pequeno travamento) e o problema é resolvido por mais 999 metros.

sábado, 7 de abril de 2018

Erro DX11 could not switch resolution (800x600 fs=1 hz=0)

Algumas pessoas enfrentaram este erro ao abrir o jogo no Windows:

Switching to resolution 800x600 failed, trying lower one
Switching to resolution 800x600 failed, trying lower one
All resolution switches have failed
Screen: DX11 could not switch resolution (800x600 fs=1 hz=0) 

Pesquisando na web vi este erro é comum em outros jogos, não é algo específico do Proton. No meu PC não aconteceu, mas seguindo relatos de outros jogadores que passaram por isso em outros jogos, vale fazer estas tentativas:

Use outra API gráfica


  • A versão PC para Windows é oferecida com outras APIs gráficas suportadas pela Unity. O ideal na plataforma é se manter no DirectX, mas se o problema persistir, experimente usar o Vulkan ou OpenGL (na pasta do jogo há atalhos para iniciar ele nesses modos). O Vulkan é suportado somente em placas de vídeo mais recentes, enquanto que o OpenGL funciona com muitas outras. Dependendo da placa de vídeo e/ou dos drivers, o jogo pode apresentar artefatos gráficos ou comportamento inesperado. Sempre mantenha seus drivers de vídeo atualizados, bem como o sistema operacional. Experimente os atalhos que vieram na pasta para ver qual funciona melhor no seu computador.

Rode no modo janela

  • Outra tentativa é marcar o modo Windowed na primeira tela do jogo, aí ele roda em modo janela (pode ser maximizada).


Tentativa no Windows 7:

  • Certifique-se de ter o Windows e os drivers de vídeo atualizados.
    Seu Windows é atualizado? As versões mais velhas podem ter problemas que já foram solucionados nas mais novas, veja no Windows Update se está tudo em dia. Vi em alguns fóruns o pessoal recomendando esta atualização da Microsoft caso use o Windows 7:
    https://www.microsoft.com/en-us/download/details.aspx?id=36805

Alternativa que talvez pegue:

Na primeira tela de seleção do jogo, marque o modo Windowed (janela). O jogo não abrirá em tela cheia assim, mas talvez pelo menos abra. Você pode maximizar a janela ou redimensioná-la livremente.

Tentativa mais fácil:
  • Clique com o botão direito no ícone do jogo, vá em Propriedades, aba Compatibilidade, e marque a opção Desabilitar otimizações de tela inteira:


    Será necessário fazer isso de novo caso você baixe uma atualização do jogo ou extraia ele novamente depois.

Tentativa com placa de vídeo da Nvidia:
  • Abra o painel de controle da Nvidia clicando com o botão direito na área de trabalho, depois vá em Monitor > Ajustar o tamanho e a posição da área de trabalho > Marque o item Sem Escala, clique no botão Aplicar... E tente abrir o jogo novamente. Veja na imagem:

  • Outra tentativa é marcar também a opção "Substituir o modo de escala definido por jogos e programas" na mesma tela acima.


É bom notar que o Proton Bus requer uma placa de vídeo com suporte a DirectX 11 (exigências da engine). Ele não vai funcionar nas placas mais antigas que só aceitavam o DirectX 9, nem nas integradas muito fracas. Quem não tem placa de vídeo até consegue rodar o jogo se o processador tiver uma GPU integrada boa (os recentes têm), mas notebooks e PCs fracos de uns anos atrás podem sofrer mais ou nem conseguir abrir.

Outra tentativa é usar a API gráfica Vulkan, se suportada pela sua placa de vídeo. Nesse caso, para abrir o jogo use o atalho .bat que tem Vulkan no nome, ele estará próximo ao ícone dele. Aparecerá uma janela preta do prompt de comando mas é normal. Você pode usar o parâmetro -force-vulkan ao executável, se quiser criar um atalho personalizado desta forma. Note que dependendo da placa de vídeo o desempenho pode ser pior ou melhor, ou nem funcionar.