8. Mundo em chunks

Só existe o que está perto do jogador. O resto é recriado quando ele volta.

O mundo é dividido em quadrados de tamanho fixo, os chunks. O jogador está sempre dentro de um deles, e o jogo mantém vivos só os 9 ao redor (uma grade 3x3). Quando o jogador cruza a borda para outro chunk, os que ficaram longe são destruídos e os que faltam são criados. Como o terreno é determinístico (semente + coordenada), o chunk recriado sai idêntico ao que foi destruído.

Setas ou WASD movem o jogador. O retângulo tracejado é a grade 3x3 (ou 5x5). Cada chunk mostra a própria coordenada.

As três contas

// 1. em que chunk o jogador está
cx = floor(jogador.x / TAMANHO_CHUNK)
cz = floor(jogador.z / TAMANHO_CHUNK)

// 2. quais chunks deveriam existir (raio 1 = grade 3x3)
desejados = {}
para dz em -raio..raio, dx em -raio..raio:
  desejados.add( (cx + dx, cz + dz) )

// 3. criar os que faltam, destruir os que sobram
para cada (c) em desejados que não está em vivos:  criar(c)
para cada (c) em vivos que não está em desejados:  destruir(c)   // ou devolver ao pool
NomeO que é
TAMANHO_CHUNKlado do chunk em unidades de mundo. Aqui 32; em Unity com 1 vértice por metro, algo entre 64 e 240.
cx, czcoordenada do chunk, inteira. O chunk (2, −1) cobre x de 64 a 95 e z de −32 a −1.
floorarredonda para baixo. Sem isso, −0,5 vira chunk 0 em vez de −1 e a grade pula na origem.
raio1 dá 3x3; 2 dá 5x5. Cada passo de raio multiplica o custo.
vivosdicionário chunk → objeto na cena, com chave "cx,cz"
poolem vez de destruir, esconder e guardar; ao criar, pegar um do pool e só repintar. Evita alocar malha nova toda hora.

A costura

O erro mais comum. Ao gerar o heightmap do chunk, usar a coordenada local (0 a 31) em vez da global (cx × 32 + x). Cada chunk sai igual ao outro e as bordas não batem. Ligue "amostrar em coordenada local" no painel e veja.
para z em 0..TAMANHO-1, x em 0..TAMANHO-1:
  gx = cx * TAMANHO + x        // global: continua de onde o vizinho parou
  gz = cz * TAMANHO + z
  altura[x, z] = fbm(gx * escala, gz * escala)

Um segundo detalhe: dois chunks vizinhos precisam compartilhar a fileira de vértices da borda. Se o chunk tem 32 quadrados, ele tem 33 vértices por lado, e o vértice 32 de um é o vértice 0 do outro. Sem isso aparece uma fresta entre eles.

Quando gerar. Gerar um chunk de 241×241 com 6 oitavas leva alguns milissegundos e, feito no frame em que o jogador cruza a borda, dá um engasgo. Os jeitos de resolver: gerar em outra thread (Unity Job System, ou Thread no Godot) e só montar a malha no frame seguinte; ou gerar o anel de fora antes de o jogador chegar nele.