sábado, 19 de novembro de 2022

Um olhar na Geração Procedural

    Outro dia encontrei uma série de tutoriais sobre como fazer landscape 3D por geração procedural no Unity. Eu tenho muito interesse em entender mais como funciona geração procedural assim como aplicações práticas, como a geração de mapas com essa técnica. Desenvolvedores independentes não podem se dar o luxo de passar semanas colocando 5 tipos diferentes de grama num cenário que o jogador pode nem passar durante a jogatina. E sim, uma série de tutoriais, por que assim que encontrei o primeiro veio uma enxurrada depois dele. 

    Quero falar um pouco do assunto, trazer um papo mais técnico pra cá mas sem entrar nos detalhes da programação ou algo assim. 


Primeiramente, o que é Geração Procedural?

    É uma técnica que se utiliza de matemáticas para gerar conteúdo, para criar coisas. É amplamente visto na geração de mapas e mundos, mas não se resume a isso, pode ser usada para gerar qualquer coisa, de textura de pão torrado a comportamento dos seres vivos simulados. 

    Exemplos famosos são o mapa do Minecraft que é gerado conforme o jogador explora os limites, e é tão grande que é praticamente infinito para os jogadores, apesar de ter sim um limite. Outro exemplo é Terraria, em que o mapa inteiro é criado de uma única vez sempre que um novo mundo é gerado, nesse caso as dimensões do terreno estão bem definidas logo no começo. O jogo Spore foi meu primeiro contato com o uso dessa técnica fora da caixinha, eles literalmente criaram alienígenas usando matemática, criaram formas de vida com culturas e tudo mais; e depois veio No Man's Sky quebrando ainda mais barreiras ao gerar o universo inteiro, desde a mais comum e insignificante pedra até os buracos negros no centro da galáxia, quase o jogo inteiro é resultado de fórmulas matemáticas. Números aleatórios? No fim são pseudo randômicos que nada mais são do que matemática de novo. 

    Como dá pra ver, tem como fazer muita coisa ao dominar as aplicações da geração procedural, mas o mais impressionante talvez seja o fato de que não exige pós doutorado em matemática para criar um universo. O conhecimento poderia vir a calhar, não estou negando isso, mas números aleatórios estão embutidos na linguagem de programação, geradores de ruídos quase sempre estão prontos para baixar e usar, e voltando o foco na Unity, não precisa se preocupar nem mesmo com a matemática de fazer curvas por que a ferramenta faz isso por você. Você só precisa unir essas ferramentas todas de um jeito inteligente e pá, tá montada uma matriz representando um mapa topográfico. Muda isso, aquilo, adiciona aquilo outro e pá, você tem um mapa climático. Tira isso, muda mais um tanto de coisa, coloca uma série de parâmetros pro gerador brincar a vontade e pá, tá pronto um gerador de qualquer coisa que a imaginação e algumas habilidades técnicas te permitem. 


Mas faz bastante sentido na prática, não faz?

    Beleza, agora que já atropelei o que é a geração procedural de forma teórica, vou atropelar a explicação de forma prática também. 

    Vamos supor um uso extremamente simplista de geração procedural. Quero, através de matemática, criar um cenário 2D ao estilo dos jogos de plataforma (os clássicos do Super Mario, Sonic, Donkey Kong, em que o personagem só anda para a direita ou para a esquerda, e pode pular para cima. Qualé, cê sabe do que tô falando né?). 

    Só definindo algumas coisas a mais, temos então essa simulação de gravidade puxando o personagem para baixo, e um bloco quadrado sólido por onde o personagem não passa. Nosso cenário vai ser bem pequeno, cabem exatamente até 10 x 10 desses blocos, onde não tem bloco o personagem passa, onde tem bloco o personagem não passa. 

    Aí vou lá e defino que o programa vai criar uma matriz de 10x10, representado todos os possíveis lugares onde eu posso colocar um bloco, e faço o código rodar todas as posições, sempre que encontrar uma posição com y=3 coloca um bloco sólido. O resultado disso é um mapa que é só uma linha reta no ar. Coloco uma roupagem bonita nesse cenário, coloco uma imagem bonita de plano de fundo, digo que meu bloco sólido é uma ponte e posiciono meu personagem em qualquer lugar com y=4 e pronto, meu cenário é gerado via matemática. Tá mais pra lógica, é verdade, mas ainda é matemática. 

    Beleza, nosso cenário está muito simples e poderia ser feito facilmente a mão, pra quê complicar? Bom, e se nosso mapa não tivesse fim? O eixo X tende ao infinito, você ficaria quanto tempo colocando blocos na mão até procurar um jeito mais inteligente de resolver o problema? Essa aqui é uma solução. Mas não estou satisfeito ainda, não vou deixar o mapa infinito, só quero que seja um novo mapa toda vez, pra não ter mapas repetidos, como faço? Traz um gerador de números aleatórios, garanta que ele tenha uma seed diferente sempre que quiser um mapa diferente, e depois seja criativo transformando o resultado dos números aleatórios em colocar ou não um bloco sólido em cada possível posição do cenário.


Um universo de possibilidades

    É aqui que entra a Arte dos geradores procedurais, você está livre para fazer como quiser, é só que técnicas muito simples e diretas vão entregar resultados muito simples e diretos, como o bloco quando y=3. E ainda assim isso é melhor que só tacar o resultado de um gerador randômico como a presença ou não de blocos, por que assim não tem controle nenhum e o resultado não fará sentido, possivelmente sendo até injogável. Coloca regras no gerador de números aleatórios e você tem algo mais imprevisível e ainda controlável, "e se definíssemos a presença do bloco aleatoriamente apenas quando y=3?" ainda não estaria perfeito mas é usável, o resultado iria parecer aquelas fases que testam sua habilidade de pular e cair no lugar certo. Aquela roupagem da ponte? Partes da ponte caíram, e pode ser que o personagem consiga passar por aqui mas pode ser que ele tenha que procurar outro caminho. Não chamei de Arte atoa, o desenvolvedor tem que ter uma noção de o que está buscando e outra noção de quais lógicas e métodos pode usar para alcançar esse resultado, sempre testando e refinando até conseguir. 

    O método de geração procedural provavelmente será mais trabalhoso que os métodos normais de criar conteúdo quando se precisa de criar pouca coisa. Mas quando sua intenção é criar 18 quintilhões de planetas únicos, fazer na mão pode levar um tempinho, melhor buscar uma fórmula pra isso. 

Nenhum comentário:

Postar um comentário