Superando limitações de flutuação para mundos do tamanho de um planeta no Unity

8

Tanto quanto eu sei, dificilmente é possível ir além de 1 milhão de unidades da origem mundial no Unity devido a problemas de precisão de ponto flutuante.

Tornar um mundo com mais de 1 milhão de unidades em raio exigiria o uso de doublevars para coordenadas ou a utilização de alguma técnica de divisão espacial para dividir uma cena massiva em pedaços hierárquicos, sendo o menor deles cerca de 10.000 unidades, ou seja, cada posição no mundo seria expressa pela hierarquia do pedaço, o objeto está dentro e floatvários vars representando sua posição local (e possivelmente rotação e escala) dentro do último pedaço.

De qualquer maneira, fazer isso exigiria a implementação de um sistema de coordenadas completamente novo, então eu gostaria de saber se isso é possível ou não no Unity e, em caso afirmativo, como posso fazê-lo funcionar com os sistemas Unity existentes, como a física e assim por diante.

PS: Não posso simplesmente mudar o mundo para a origem conforme o jogador se move, pois quero que as coisas aconteçam simultaneamente ao redor do planeta.

Obrigado!

Maks Maisak
fonte

Respostas:

5

Você está pensando em termos muito estáticos.

Só porque um objeto está a meio mundo de distância não requer nenhum problema. Se as coordenadas da entidade são armazenadas em relação ao bloco, e não em relação ao mundo, isso é trivial. Bem-vindo à maneira que você faria se estivesse escrevendo um mundo voxel em código nativo.

Então, vamos assumir um conceito chamado locales . É um conjunto de pedaços que estão próximos um do outro. O que importa é que o espaço flutuante interno para um determinado local nunca exceda o limite de segurança. Você precisa determinar quais são os seus códigos de idioma de processamento discretos. Comece pegando todos os pedaços que caem dentro de um raio da posição da entidade n (pode ser o player ou outra coisa). No meu mecanismo atual, certifico-me de que, mesmo que um pedaço de dois códigos de idioma diferentes se sobreponha, esses códigos de idioma sejam mesclados em um código de idioma / conjunto de blocos exclusivos. Isso garante que você nunca processe todas as entidades em um único bloco mais de uma vez, em um determinado quadro.

Agora que você possui seus códigos de idioma / partes, você pode executar a lógica do jogo neles e em seu conteúdo. E não importa o quão longe eles estão longe do jogador ou de origem. O que importa é que você obtenha um pedaço que é aproximadamente central para cada conjunto, trate isso como a origem, ou seja, float[0.0,0.0,0.0] e trabalhe para fora a partir daí. Dado o alcance de visão típico de um jogo, garanto que você nunca precisará ver mais do que alguns kms, o que é muito possível float, sem problemas sérios.

Além do Unity, uma opção é escrever um mecanismo a partir do zero, eu acho, e usar algo como libfixmath, onde você ainda pode usar pontos decimais, mas como eles não flutuam , eles nunca terão esses problemas de precisão. Mas garanto que você precisará de blocos e localidades por outros motivos, portanto, provavelmente não vale a pena.

Engenheiro
fonte
Você disse que nunca precisarei ver a mais de alguns quilômetros de distância, mas e quanto a um mundo do tamanho de um planeta, que eu deveria ser capaz de observar completamente do espaço (veja outerra )?
Maks Maisak
@MaksimMaisak A lógica do jogo requer precisão numérica; renderização não. Você nunca precisará ver o mundo preciso e detalhado do espaço sideral. Há uma certa altura em que você pode alternar do sistema preciso e no terreno que eu descrevi acima para a menos precisa, com perspectiva de espaço, sem problemas (se você jogar suas cartas corretamente). Mas lembre-se de que há uma diferença entre a renderização e a lógica do jogo.
Engenheiro de
E como você divide o espaço em pedaços? Você começa com partes e agrupa-as em localidades, ou começa com localidades e se divide em partes?
Maks Maisak
Você começa com pedaços. "Locales" aqui significa apenas "bairros de partes", portanto o conceito de parte é o pré-requisito.
Engenheiro de
Como um pedaço pode estar "sobreposto" então?
Maks Maisak
6

Essa é uma pergunta que freqüentemente aparece. Terei a liberdade de encaminhá-lo para outra resposta bastante detalhada que já dei ao mesmo problema, em vez de apenas repeti-lo aqui: É possível um sistema de coordenadas personalizado no Unity

A partir daí, o que eu mais sugeriria é que você leia o artigo incrível em: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.471.7201&rep=rep1&type=pdf . Ele compara algumas das maneiras de resolver o problema que você descreve (incluindo as coordenadas locais, conforme descrito pelo Engenheiro Arcano em sua resposta) e entra em detalhes sobre a famosa solução de origem flutuante atualmente. O que é, de fato, o que eu procuraria na maioria dos casos (na verdade, é isso que estou usando no meu aplicativo).

Claro, você mencionou que a solução de origem flutuante não se adequa às suas necessidades. Mas isso pode não ser o caso, mesmo que você queira que as coisas continuem acontecendo em partes muito distantes do mundo. Você pode ter praticamente qualquer IA acontecendo onde quiser - você não deve fazer verificações de colisão ou posicionamento preciso muito longe do jogador (ou seja, além do limite de imprecisão do flutuador). Mas de qualquer maneira, francamente, em aplicativos reais, você provavelmente nunca seria capaz de ter tantas colisões e posicionamento em um jogo devido a limitações de processamento. E ainda assim, pode haver soluções até para essa limitação que você vê na solução de origem do flutuador, dependendo das características do seu jogo. Novamente, sugiro que você não descarte essa solução antes de uma leitura mais completa sobre ela.

Ainda assim, se você decidir tentar os sistemas de coordenadas locais (que podem se tornar uma solução bastante complexa dependendo de onde você for), o segundo item da minha resposta vinculada será para você. A peça mais importante é o artigo escrito pelo cara que implementou essa solução no jogo pioneiro Dungeon Siege: http://scottbilas.com/files/2003/gdc_san_jose/continuous_world_paper.pdf

Há também um vídeo de alguns anos atrás, em que as pessoas da Unity comentam sobre essa solução e até explicam uma implementação moderna do conceito no Unity:

https://www.youtube.com/watch?v=VKWvAuTGVrQ

Espero que ajude.

MAnd
fonte
3

Não tenho certeza se você já optou por uma solução, mas gostaria de mencionar outros dois recursos que podem ser úteis para você e outros leitores no futuro.

  • Esta recente conversa do CppCon: "Desmistificação do ponto flutuante" , que é muito relevante, independentemente da linguagem de programação. Um ponto muito interessante apresentado sobre a precisão é que o ponto ideal da precisão da flutuação está entre a faixa [-1, + 1]. Portanto, carros alegóricos normalizados são o melhor caminho a percorrer, se você puder usá-los.

  • Outro lugar que você pode querer procurar para ter algumas idéias é no clássico jogo Dungeon Siege . O jogo usava um sistema mundial contínuo baseado em nó / bloco e todas as posições eram relativas ao nó atual. Há uma descrição muito detalhada do sistema usado pelo jogo neste whitepaper . Também escrevi alguns parágrafos sobre isso no meu blog . Essa configuração era nova na época, mas provavelmente não é tão útil hoje em dia, o artigo acima mencionado menciona alguns dos problemas que eles tiveram. No entanto, é interessante de uma perspectiva histórica e ainda pode servi-lo como uma fonte de idéias e inspiração.

glampert
fonte