Atualmente, estou trabalhando em um mundo infinito, principalmente inspirado em minecraft.
Um Chunk consiste em blocos 16x16x16. Um bloco (cubo) é 1x1x1.
Isso funciona muito bem com um ViewRange de 12 pedaços (12x16) no meu computador. Bem.
Quando mudo a altura do Chunk para 256, isso se torna - obviamente - incrível.
Então, basicamente, o que eu quero fazer é empilhar pedaços. Isso significa que meu mundo pode ter [∞, 16, ∞] pedaços grandes.
A questão agora é como gerar pedaços em tempo real?
No momento, gero pedaços circulares não existentes em torno da minha posição (perto ou longe). Como ainda não empilhe pedaços, isso não é muito complexo.
Como nota lateral importante aqui: eu também quero ter biomas, com diferentes alturas mín. / Máx. Assim, em Bioma Plains a camada mais alta com blocos seriam 8 (8x16) - em Bioma Montanhas a camada mais alta com blocos seriam 14 (14x16). Apenas como exemplo.
O que eu poderia fazer seria carregar 1 pedaço acima e abaixo de mim, por exemplo.
Mas aqui estaria o problema , que as transições entre diferentes átomos poderiam ser maiores que um pedaço de y.
Meu pedaço atual de carregamento em ação
Para completar, meu atual algoritmo de carregamento de blocos
private IEnumerator UpdateChunks(){
for (int i = 1; i < VIEW_RANGE; i += ChunkWidth) {
float vr = i;
for (float x = transform.position.x - vr; x < transform.position.x + vr; x += ChunkWidth) {
for (float z = transform.position.z - vr; z < transform.position.z + vr; z += ChunkWidth) {
_pos.Set(x, 0, z); // no y, yet
_pos.x = Mathf.Floor(_pos.x/ChunkWidth)*ChunkWidth;
_pos.z = Mathf.Floor(_pos.z/ChunkWidth)*ChunkWidth;
Chunk chunk = Chunk.FindChunk(_pos);
// If Chunk is already created, continue
if (chunk != null)
continue;
// Create a new Chunk..
chunk = (Chunk) Instantiate(ChunkFab, _pos, Quaternion.identity);
}
}
// Skip to next frame
yield return 0;
}
}
fonte
Não acredito que você possa fazer isso simplesmente carregando determinadas camadas por causa do problema de transições.
Minha inclinação seria armazenar alguns metadados com cada pedaço:
1) O bloco é totalmente de ar. Nesse caso, não há necessidade de renderizá-lo.
2) Para cada face do bloco é opaco. Um rosto opaco significa que você não precisa considerar o próximo pedaço. (Observe, porém, que dependendo de onde o pedaço está, pode haver até três faces envolvidas - um pedaço deve ser renderizado se qualquer um dos três não for opaco. Eu suspeito que seja melhor pré-calculado - render tanto ou b1 é visível e tem uma face não opaca f1 ou b2 é visível tem uma face não opaca f2 ou b3 é visível tem uma face não opaca f3.)
Infelizmente, existem mais de 7000 pedaços dentro da sua faixa de visão de 12 pedaços. No entanto, eu esperaria que poucos locais tenham mais de três blocos verticais que realmente precisam ser renderizados usando essa abordagem, que reduz a contagem de blocos para provavelmente não mais que 1500.
Eu aplicaria o mesmo tipo de lógica em um pedaço - quando você carrega um pedaço, calcula quais junções são transparentes e quais são opacas tocando em opacas - você só precisa renderizar rostos onde alguém possa vê-las. (Observe que no Minecraft você tem três tipos de bloco - transparente, opaco e que altera a visão - vidro, portas, cercas etc. Você pode pular apenas transparente-transparente e opaco-opaco.)
fonte