Superar las limitaciones de flotación para mundos del tamaño de un planeta en Unity


8

Hasta donde sé, ir más allá de 1 millón de unidades desde el origen mundial en Unity es casi imposible debido a problemas de precisión de coma flotante.

Hacer un mundo de más de 1 millón de unidades en radio requeriría usar doublevars para las coordenadas o utilizar alguna técnica de división espacial para dividir una escena masiva en trozos jerárquicos con el más pequeño de ellos alrededor de 10 000 unidades, es decir, cada posición del espacio mundial se expresaría por la jerarquía de fragmentos dentro del objeto y un grupo de floatvariables que representan su posición local (y posiblemente rotación y escala) dentro del último fragmento.

De cualquier manera, hacer esto requeriría implementar un sistema de coordenadas completamente nuevo, por lo que me gustaría saber si eso es posible o no en Unity, y si es así, ¿cómo puedo hacer que funcione con sistemas Unity existentes como la física, etc.

PD: No puedo simplemente mover el mundo a su origen a medida que el jugador se mueve, ya que quiero que las cosas sucedan simultáneamente en todo el planeta.

¡Gracias!

Respuestas:


5

Estás pensando en términos muy estáticos.

El hecho de que un objeto esté a medio mundo de distancia no requiere ningún problema. Si las coordenadas de la entidad se almacenan en relación con el fragmento en lugar de en relación con el mundo, esto es trivial de lograr. Bienvenido a la forma en que tendría que hacerlo si estuviera escribiendo un mundo vóxel en código nativo.

Así que supongamos un concepto llamado locales . Es un conjunto de fragmentos que están muy cerca uno del otro. Lo que importa es que el espacio flotante interno de un lugar determinado nunca exceda el límite de seguridad. Debe determinar cuáles son sus configuraciones regionales de procesamiento discretas, comience tomando todos los fragmentos que se encuentren dentro de un radio de la posición de la entidad n (podría ser el jugador u otra cosa). En mi motor actual, me aseguro de que si se superpone incluso un fragmento de dos configuraciones regionales diferentes, estas configuraciones regionales se fusionan en una configuración regional / conjunto de fragmentos únicos. Esto garantiza que nunca procese todas las entidades en un solo fragmento más de una vez, en un marco determinado.

Ahora que tiene sus configuraciones regionales / conjuntos de fragmentos, puede realizar la lógica del juego en ellos y sus contenidos. Y no importa qué tan lejos estén del jugador o del origen. Lo que importa es que obtienes un fragmento que es aproximadamente central en cada conjunto, trata eso como el origen, es decir, float[0.0,0.0,0.0], y avanza hacia afuera desde allí. Dado el rango de visión típico en un juego, te garantizo que nunca necesitarás ver más de unos pocos kms, lo cual es muy factible float, sin problemas serios.

Aparte de Unity, una opción es escribir un motor desde cero, supongo, y usar algo como libfixmath, donde todavía puedes usar puntos decimales, pero debido a que no flotan , nunca tendrán estos problemas de precisión. Pero le garantizo que necesitará fragmentos y configuraciones regionales por otros motivos, por lo que probablemente no valga la pena el esfuerzo.


Dijiste que nunca necesitaré ver a más de unos pocos kilómetros de distancia, pero ¿qué pasa con un mundo del tamaño de un planeta, que debería ser capaz de observar completamente desde el espacio (ver outerra )?
Maks Maisak

@MaksimMaisak La lógica del juego requiere precisión numérica; el renderizado no. Nunca necesitará ver el mundo detallado y preciso desde el espacio exterior. Hay una cierta altura a la que puede cambiar del sistema preciso en el terreno que describí anteriormente a una perspectiva espacial menos precisa, sin problemas (si juega bien sus cartas). Pero tenga en cuenta que hay una diferencia entre el renderizado y la lógica del juego.
Ingeniero

¿Y cómo se divide el espacio en trozos? ¿Empiezas con fragmentos y los agrupas en locales, o comienzas con locales y los divides en fragmentos?
Maks Maisak

Empiezas con trozos. "Locales" aquí solo significa "vecindarios de trozos", por lo que el concepto de trozos es el requisito previo.
Ingeniero

¿Cómo puede una parte "superponerse" entonces?
Maks Maisak

6

Esa es una pregunta que surge con frecuencia. Me tomaré la libertad de remitirle a otra respuesta bastante detallada que ya le di al mismo problema, en lugar de repetirlo aquí: ¿es posible un sistema de coordenadas personalizado en Unity?

A partir de ahí, lo que más te sugeriría es que leas el increíble artículo en: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.471.7201&rep=rep1&type=pdf . Compara algunas de las formas de abordar el problema que describe (incluidas las coordenadas locales, tal como lo describe el Ingeniero Arcano en su respuesta) y entra en detalles sobre la famosa solución de origen flotante de hoy en día. Que es, de hecho, lo que buscaría en la mayoría de los casos (de hecho, eso es lo que estoy usando en mi aplicación).

Claro, mencionó que la solución de origen de flotación no se adapta a sus necesidades. Pero ese puede no ser el caso, incluso si desea que las cosas sigan sucediendo en partes muy distantes del mundo. Puedes tener prácticamente cualquier IA que ocurra donde quieras, simplemente no deberías estar haciendo controles de colisión o posicionamiento preciso demasiado lejos del jugador (es decir, más allá del umbral de inexactitud de flotación). Pero de todos modos, francamente, en aplicaciones reales probablemente nunca podrías tener tanta colisión y posicionamiento en un juego debido a las limitaciones de procesamiento. Y aún así, puede haber soluciones incluso para esa limitación que ves en la solución de origen de flotación, dependiendo de las características de tu juego. Nuevamente, le sugiero que no descarte esa solución antes de una lectura más exhaustiva al respecto.

Aún así, si decide que debe probar los sistemas de coordenadas locales (que pueden convertirse en una solución bastante compleja dependiendo de dónde vaya), entonces el segundo elemento en mi respuesta vinculada es para usted. La pieza más importante es el documento escrito por el tipo que implementó por primera vez esa solución en el juego pionero Dungeon Siege: http://scottbilas.com/files/2003/gdc_san_jose/continuous_world_paper.pdf

También hay un video de hace un par de años, donde las personas de Unity comentan sobre esa solución e incluso explican una implementación moderna del concepto en Unity:

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

Espero eso ayude.


3

No estoy seguro si ya se ha conformado con una solución, pero me gustaría mencionar otros dos recursos que podrían ser útiles para usted y otros lectores en el futuro.

  • Esta reciente charla de CppCon: "Desmitificando el punto flotante" , que es muy relevante independientemente del lenguaje de programación. Un punto muy interesante presentado sobre la precisión es que el punto óptimo de la precisión del flotador está entre el rango [-1, + 1]. Por lo tanto, los flotadores normalizados son la mejor opción si puedes usarlos.

  • Otro lugar en el que querrás buscar algunas ideas es el clásico juego Dungeon Siege . El juego utilizaba un sistema mundial continuo basado en nodos / mosaicos y cada posición era relativa al nodo actual. Hay una descripción muy detallada del sistema utilizado por el juego en este documento técnico . También escribí algunos párrafos al respecto en mi blog . Esta configuración era novedosa en ese momento, pero probablemente no sea tan útil hoy, el documento vinculado anteriormente menciona algunos de los problemas que tenían. Sin embargo, es interesante desde una perspectiva histórica y aún puede servirle como fuente de ideas e inspiración.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.