- Quad sphere afinado para mapear la cuadrícula al globo con menos distorsión.
- Shells que duplican resolución para mantener tamaños y alinear aristas.
- Direcciones de bloque Sector→Shell→Chunk→Bloque y vecinos 1↔4.
Imaginar Minecraft sobre un planeta redondo suena a locura… hasta que alguien se pone y lo crea como demostración técnica. Eso es justo lo que propone Blocky Planet: un mundo de voxeles con forma de esfera, donde cada bloque encaja en un sistema de gravedad que apunta al centro del planeta.
La gracia no está solo en que el terreno sea agujereable y editable, sino en las soluciones ingeniosas necesarias para que los cubos se comporten como cubos sobre una superficie curva. En este artículo te contamos, con todo detalle y en castellano, cómo se ha resuelto el mapeo esférico, la estructura del planeta, la búsqueda de vecinos, la gravedad del jugador y la generación de terreno, además de una lista de ideas de futuro.
Qué es Blocky Planet y cómo se juega
Blocky Planet es una demo tecnológica desarrollada en Unity cuyo objetivo es mapear voxeles cúbicos sobre una esfera completamente destruible. Puedes colocar o quitar más de una veintena de tipos de bloques, y todo el planeta se genera de forma procedural.
Si quieres probarlo, el autor publica compilaciones en su página de Itch.io, con una versión nativa para Windows y una build web jugable en el navegador (con alguna excentricidad propia del navegador). La idea nació al toparse con una demo antigua de Jordan Peck, y como amante de la geometría procedural y los voxel games, el desarrollador se propuso rehacerla añadiendo elementos que echaba en falta, como texturas de bloques y destrucción a gran escala.
¿Habrá juego completo? La respuesta franca es que no hay planes firmes: es un proyecto personal, y el salto de demo a producto pulido es enorme. Aun así, el autor no descarta sacar alguna que otra actualización cuando el tiempo lo permita.
En cuanto al esfuerzo, el núcleo del código se levantó en poco más de un mes a unas 15 horas semanales, apoyándose en experiencia previa con voxeles. Lo más duro fue hacerlo esférico; paradójicamente, escribir e ilustrar la publicación técnica llevó el doble de tiempo. El desarrollo se ha hecho con Unity 6 y C#, usando el sistema de Jobs y el compilador Burst, pero sin entrar del todo en DOTS porque, para este caso, ofrece una mejora de rendimiento moderada a cambio de una complejidad mayor y la ausencia de algunas características básicas.
¿Código fuente? De momento no se comparte, en parte porque no está lo bastante pulido. Respecto a las texturas, todas son artesanales: pixel art o generadas por scripts. Curiosidad: muchas texturas estilo Minecraft pueden aproximarse tintando ruido aleatorio. Si tienes dudas o ideas, la conversación se centraliza en el hilo de Reddit correspondiente.
Por qué una esfera de bloques no es trivial
Levantar una esfera compuesta de cubitos con un filtro geométrico es fácil: basta con quedarte con los bloques cuyo centro cae a cierta distancia del origen y listo, una esfera de voxeles. El problema aparece al jugar: la superficie no queda alineada con la gravedad y se siente raro construir “hacia arriba” o caminar.
Lo que se busca es que la cara superior del bloque mire al espacio y la inferior al núcleo, alineando verticales con la gravedad. Para ello, hay dos retos principales que resolver: 1) cómo mapear una cuadrícula 2D sobre una esfera 3D y 2) cómo mantener el ancho de los bloques a medida que crecemos en profundidad hacia afuera.
Mapear un plano a una esfera: la vieja pesadilla cartográfica
Gauss nos aguó la fiesta hace siglos: no existe proyección perfecta de un plano sobre una esfera. Cualquier proyección distorsiona algo: superficies, ángulos o distancias. Los mapas “todo en un rectángulo” se llevan la peor parte, porque las líneas superiores e inferiores convergen en puntos de la esfera provocando una distorsión salvaje.
Para videojuegos, una estrategia habitual es el conocido quad sphere: dividir la esfera en seis sectores equivalentes, uno por cara del cubo, y mapear a cada cara su propia cuadrícula cuadrada. Se empieza con un cubo centrado en el origen, se subdividen sus caras y se empujan los vértices hacia afuera hasta que queden sobre la esfera unitaria normalizándolos. El cubo se infla como un globo y obtenemos quads (ya no son cuadrados perfectos) sobre la superficie.
El quad sphere estándar aún deforma más de la cuenta, pero se puede reducir predeformando la cuadrícula plana para compensar la normalización. El resultado: quads que preservan mucho mejor área, ángulos y lados. La diferencia se nota especialmente en el encuentro de dos sectores, donde con el mapeo básico los bloques se aplastan en rectángulos, mientras que con el ajuste mejorado conservan su aspecto más cuadrado.
Una curiosidad: si ignoras cualquier proyección y usas una esfera “cuadradota” literalmente, el juego es técnicamente jugable. Eso sí, la sensación es como ir siempre en cuesta, porque la gravedad sigue tirando hacia el centro y la normal de la superficie no coincide con esa dirección.
Profundidad y distorsión: capas, shells y multiplicaciones por dos
En un mundo plano, apilar capas idénticas funciona y punto. En una esfera, si dejas la altura del bloque constante y apilas sin más, aparecen bloques finísimos cerca del centro y mucho más anchos en superficie. Para mitigarlo, hay que añadir más bloques por capa a medida que te alejas del núcleo.
Calcular la cantidad exacta por capa haría que los bordes no casaran bien, estropeando paredes y pilares. La solución práctica es escalonar el aumento: solo sumar bloques cuando la distorsión lo exija. Además, para alinear las costuras entre capas, la cantidad de bloques debe crecer por un múltiplo entero; elegir 2 minimiza la distorsión acumulada.
Así nacen los shells: grupos de capas donde las aristas encajan perfectamente. Al pasar de shell, se cuadruplica (2^2) el número de bloques por capa para mantener tamaños próximos. Esto hace que, dentro de un shell, los bloques del inicio sean aproximadamente un cuarto del tamaño respecto a los del final, un compromiso razonable para preservar la alineación y, de paso, obtener una malla regular muy cómoda para el código.
Estructura interna del planeta: sectores, shells y chunks
En mundos planos tipo Minecraft, el almacenamiento va por chunks columna que abarcan de mínimo a máximo de altura, y se trocean en chunks de render. Un ejemplo típico: 16x320x16 para la columna y 16x16x16 para render.
En la esfera, el mundo se divide en seis sectores en forma de cuña, uno por dirección de los ejes del cubo original. Esta elección viene del quad sphere de la superficie. Cada sector se subdivide “verticalmente” en shells, que crecen tanto en número de capas como en bloques por capa conforme te alejas del origen. No hay un límite teórico de shells, así que la estructura puede cubrir el espacio 3D (aunque en la práctica se fija una altura máxima de construcción por conveniencia).
Para que el motor vaya fino, esos shells de tamaño variable se separan en chunks regulares 16x16x16. En versiones tempranas se han mostrado vistas “explosionadas” del mundo para visualizar cómo encaja todo por dentro.
Direcciones y direcciones: cómo se “domicilia” un bloque
Para colocar o quitar bloques necesitamos traducir una posición del mundo a una dirección de bloque única. Igual que una dirección postal, vamos de lo general a lo concreto: Sector → Shell → Chunk → Bloque.
Una representación sencilla en C# podría ser así (adaptada y traducida): sectorIndex, shellIndex, chunkIndex, blockIndex donde los índices acotan rangos válidos. El cálculo desde coordenadas de mundo tiene varios pasos (menos triviales que en plano), pero el concepto es directo.
struct BlockAddress {
public int sectorIndex; // 0 - 5
public int shellIndex; // 0 - +Inf
public int3 chunkIndex; // [0-n, 0-n, 0-n]
public int3 blockIndex; // [0-15, 0-15, 0-15]
}
En un mundo plano, esta traducción es inmediata; en la esfera, hay que considerar la topología de sectores y shells para resolver el índice de forma consistente.
Encontrar vecinos: el quebradero de cabeza definitivo
La operación de “quién está al lado” es esencial para optimizar el render (solo dibujar caras visibles) y para acciones de edición múltiple. En un mundo cúbico plano, trivial. En la esfera, lograr consistencia ha sido el mayor desafío.
Objetivo: dado un BlockAddress y una de las seis direcciones de eje (±X, ±Y, ±Z), devolver la dirección del bloque vecino. Dentro del mismo chunk o shell no hay misterio, pero cruzar límites verticales de shell o pasar de un sector a otro complica la cosa.
En los límites verticales de shell, rompemos una suposición básica: no siempre hay un único vecino. Como al pasar a un shell con el doble de resolución cada cara se subdivide por 2, un bloque en la parte superior del shell N mapea a cuatro bloques distintos en la base del shell N+1. A la inversa, esos cuatro comparten un único vecino descendente. El código debe contemplar estas correspondencias 1↔4.
Los bordes entre sectores son otro lío: cada sector tiene su sistema 2D local (u, v) y, al “pegar” caras como un desplegable de cubo, pueden darse dos desajustes inevitables: intercambio de ejes (u↔v) y ejes invertidos. Se resuelve con intercambios y giros de índices, siempre que la convención de pegado del “net” del cubo se mantenga estricta en todo el proyecto.
Física del jugador: gravedad al centro y un empujón orbital
El controlador del jugador es físico estándar con rigidbody, pero con un cambio clave: se desactiva la gravedad global y se aplica una gravedad personalizada que tira hacia el centro del planeta.
La fuerza no busca exactitud newtoniana; es “a ojo” para que sea jugable: constante sobre la superficie para que el movimiento sea predecible, y decreciente hacia 0 al excavar rumbo al núcleo, simulando el efecto de masas que te atraen desde todas direcciones. Además, hay una habilidad de “impulso” al mantener pulsada la barra espaciadora en el aire, que contrarresta y supera la gravedad lo bastante como para entrar en órbita.
Generación del terreno: ruido suave, agua y biomas polares
Como en muchos generadores, la altura del terreno se deriva de ruido suave. A partir de esa altura, el tipo de bloque se determina por reglas simples: primero todo es aire; si un bloque cae por debajo de la altura de terreno, se convierte en piedra; cerca de la parte superior de la “columna” se transforman en hierba o tierra según la distancia al tope; por debajo del nivel de agua, la hierba pasa a arena y el aire a agua.
En mundos planos se usa ruido 2D para un heightmap que consultas por (x, z). En la esfera hay dos problemas: el ruido debe “embaldosarse” sin costuras y el mapeo 2D→3D distorsiona. La vía corta es muestrear directamente un ruido 3D sobre la esfera, sin seams y sin distorsión de proyección. Se toma por defecto la unidad, pero puedes muestrear varias esferas (escalas) para distintos tamaños de planeta y desplazar el volumen de ruido para semillas aleatorias.
Para biomas, de momento se usa un sistema sencillo: bosque y ártico. Se decide por la distancia angular a los polos (Norte y Sur): si cae por debajo de un umbral, se asigna ártico; en caso contrario, bosque. Se añade un ruido suave al umbral para evitar fronteras perfectamente circulares entre biomas.
Estructuras de bloques: pegar sin romper la topología
Una “estructura” es cualquier patrón guardado de bloques que se puede pegar en el mundo: desde árboles de la generación procedural hasta construcciones del jugador guardadas como plantillas. Se almacenan como arreglos 3D (zona origen) y, en teoría, sería cuestión de copiar cada bloque a su posición en la zona destino.
Pero hay trampas topológicas. En las esquinas donde se encuentran tres sectores, se rompe la retícula regular: se juntan tres bloques en lugar de cuatro. Y en los límites verticales de shell, puede haber hasta cuatro vecinos verticales en vez de uno, así que no siempre es posible definir una zona destino cúbica isomorfa a la zona origen.
En lugar de prohibir el pegado en zonas conflictivas, el sistema interpreta la estructura como un origen más un conjunto de desplazamientos relativos. Desde ese bloque raíz, se navega por direcciones de vecino hasta ubicar cada bloque de la estructura. Funciona en todo el planeta; en zonas complicadas puede quedar “gracioso”, pero es preferible a tener áreas muertas donde nada se puede colocar.
Detalles prácticos y preguntas frecuentes
¿Dónde descargar? En Itch.io está la última compilación, con mejor rendimiento en Windows; la versión WebGL es jugable pero menos estable. ¿Por qué se hizo? Por el reto de geometría procedural y voxeles, y para cubrir carencias de demos anteriores: texturas por bloque y destrucción a lo bestia.
¿Se convertirá en juego comercial? Lo más probable es que no, al menos sin el nivel de calidad necesario para cobrar, por falta de tiempo. ¿Cuánto costó hacerlo? Aproximadamente un mes de código a 15 h/sem, con la experiencia en voxeles a favor. Crear el post técnico y sus ilustraciones fue lo que más se alargó.
¿Tecnología? Unity 6 con C#, Jobs y Burst (sin DOTS completo); texturas hechas a mano o por scripts. ¿Código abierto? No por ahora. ¿Dudas o propuestas? Al hilo de Reddit; si la sugerencia es razonable, igual cae en una actualización.
Lo que queda por hacer
En la hoja de ideas figuran varios objetivos que podrían llegar si el tiempo lo permite. El más ambicioso es un sistema solar al estilo Outer Wilds, con varios planetas y lunas de bloques entre los que desplazarse. Las órbitas podrían ser un reloj mecánico simple o un modelo gravitatorio más complejo inspirado en experimentos como el de Sebastian Lague.
Otro frente interesante es la gravedad por chunk, calculada dinámicamente según la masa/bloques de cada zona para lograr comportamientos más realistas bajo la superficie sin penalizar rendimiento. También está sobre la mesa permitir colisiones entre cuerpos: asteroides cúbicos chocando contra planetas; solo de pensarlo, duele la cabeza, así que no lo esperes pronto.
Más objetivos: generación de cuevas que conecten superficie y núcleo, un sistema de biomas “de verdad” que tenga en cuenta la latitud y otros factores, y una iluminación basada en voxeles que complemente la luz directa y sombras de Unity con un GI estilo Minecraft clásico.
Profundizando en el mapeo: receta del quad sphere afinado
Para quienes quieran replicarlo, la receta del quad sphere es: partir de un cubo centrado, subdividir caras en cuadrículas y normalizar cada vértice para que se apoye en la esfera unitaria. El paso extra de calidad es una predeformación de la cuadrícula en cada cara que atenúa la distorsión introducida por la normalización, de forma que los quads resultantes preserven mucho mejor área y ángulos.
La clave para encajar bordes entre sectores es fijar un “net” del cubo y no romperlo jamás: qué cara pega con cuál y cómo (si se intercambia u por v, si se invierte el sentido). A partir de esa convención, el cálculo de vecinos entre sectores se reduce a permutar e invertir índices de manera determinista.
Profundizando en shells: cuándo y cómo multiplicar
El criterio para “ascender” a una resolución mayor puede basarse en error de área/longitud: cuando el bloque se separa demasiado del tamaño objetivo, se duplica la resolución en u y v para el siguiente shell. Por esa elección, al cruzar verticalmente shells el vecindario pasa a ser 1→4 o 4→1 según la dirección, y conviene tener utilidades que iteren esos vecinos con seguridad para no dejar agujeros en el mallado ni en la lógica de edición.
A nivel de implementación, agrupar bloques por shells también permite estructurar la memoria en zonas compactas y coherentes con el patrón de acceso (lecturas locales más frecuentes), lo que se lleva de maravilla con Jobs y Burst en Unity para paralelizar generación, actualización y meshing.
Meshing y visibilidad: caras visibles y límites limpios
Aunque no se detalla todo el pipeline, el cálculo de vecinos se usa para ocultar caras internas, muy parecido a cualquier motor de voxeles: solo se generan caras cuando al otro lado no hay bloque sólido. En los límites de shell y sector, donde la topología cambia, ese cálculo necesita los mapeos comentados para que no aparezcan costuras ni faltas de polígonos.
Con shells bien definidos y chunks regulares, se puede actualizar por regiones tras editar o destruir bloques, evitando resincronizar el planeta entero. Esto mantiene estable el rendimiento incluso con destrucciones grandes y repetidas.
Blocky Planet demuestra que un planeta esférico de voxeles no es solo una idea simpática, sino un ejercicio serio de geometría y arquitectura de datos que, bien resuelto, se siente natural al jugar. El equilibrio entre mapeo esférico, shells para profundidad, direcciones de bloque consistentes, gravedad agradable y un generador de terreno sin costuras ofrece una base sólida para seguir experimentando con biomas, cuevas, iluminación y, quién sabe, un pequeño sistema solar de mundos de cubitos para perderse durante horas.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.