Sistemas que criam ecossistemas: Design de jogos emergente

Com scripts simples, os designers de jogos podem criar sistemas em seus jogos que resultam em uma jogabilidade interessante e inesperada – uma espécie de caos organizado para encantar e cativar os jogadores. Conversamos com o designer de jogos Christo Nobbs, que explica sua abordagem para projetar uma jogabilidade emergente com a ajuda de alguns recursos importantes do Unity .
Com base em anos de conversas com criadores individuais e estúdios de jogos, sabemos que quando os designers de jogos criam jogabilidade e mecânicas de design no Unity, eles podem demonstrar a visão do jogo de forma clara e detalhada para o resto da equipe.
Criamos um novo e-book, The Unity game designer playbook, para designers de jogos que querem aprender como prototipar, criar e testar jogabilidade no Unity. Designers de jogos novos e experientes podem usar este guia ao começar a adicionar habilidades do Unity ao seu perfil.
Christo Nobbs, um designer técnico sênior de jogos especializado em design de jogos de sistemas e Unity (C#), foi um colaborador do e-book. Nesta postagem do blog, a primeira de uma série para designers de jogos, ele expande algumas das dicas e exemplos para projetar sistemas que ele forneceu no e-book.

No design de jogos, um sistema útil deve ter uma função clara, armazenar dados e ser modular. Dessa forma, ele não só pode interagir com outro sistema, como também interage consigo mesmo em outros GameObjects de diversas maneiras. Ao pensar em um sistema de jogo sistêmico, muitas vezes também pode ajudar imaginá-lo não como uma arquitetura completa, mas como uma parte da funcionalidade que pode ser executada recursivamente pelo jogo.
Ao combinar esses sistemas, você pode criar ecossistemas únicos que reagem às ações do jogador e são equilibrados usando “alavancas de design” (em oposição a valores ocultos e codificados). Essas alavancas são colocadas em prática para manipular seus dados, resultando em uma jogabilidade sistêmica.
A maioria dos jogos terá pelo menos um sistema, seja uma mecânica única com valores a serem ajustados ao longo do jogo ou uma rede de sistemas. Em um jogo de estratégia como Age of Empires, em que o jogador precisa aprender a aproveitar e manipular recursos para progredir e derrotar oponentes, são ecossistemas complexos que governam a jogabilidade.
No final das contas, cabe aos próprios designers do jogo decidir como eles querem que o jogador prossiga no jogo. A jogabilidade deve ser definida em um caminho linear e guiado ou deve ser conduzida por um sistema ou uma combinação de sistemas que permitam resultados orgânicos e emergentes?
Ao projetar um sistema pequeno, sua modularidade e capacidade de interagir consigo mesmo e com outros sistemas devem ser priorizadas, porque esses recursos podem gerar loops de jogabilidade interessantes. Você quer pensar sobre as possíveis cadeias de reações que podem resultar de um sistema colidindo consigo mesmo por meio de outro objeto, ou de dois sistemas simples criando uma justaposição para atuarem juntos. Sempre tente criar sistemas cuja função seja clara para o jogador, para que ele tenha uma chance razoável de aprender como qualquer sistema funciona e obter uma vantagem.

Um exemplo de reação em cadeia é o do jogo Oxygen Not Included, onde o objetivo do loop principal é equilibrar vários sistemas para atingir um estado de utopia simbiótica e continuar progredindo. Outro exemplo vem de Divinity Original Sin 2, da Larian Studios, onde mobs que explodem para atacar não podem mais fazê-lo se o jogador os molhar, tornando a luta mais fácil. Ou o jogador pode atear fogo no chão para se proteger do grupo quando ele correr em sua direção.
Um sistema modular pode agregar mais valor ao seu jogo porque você pode usar partes de um sistema para criar outro sistema diferente. Um recurso do Unity que Christo usa para quase tudo são as Curvas de Animação. Como ele diz, “o processamento de seus dados é quase sempre o mesmo. Eles dão mais controle do que um único valor para equilibrar. E você pode adicionar facilidade à mecânica ou até mesmo substituir os limites do sistema para ajustar um detalhe.”
Uma abordagem modular ao design também permite que você informe os programadores com a maior precisão possível, tornando mais eficiente para eles editar e depurar sistemas de jogo e reutilizá-los em diferentes configurações ao longo do jogo.
Alavancas de design são úteis para ajustar valores e manipular um resultado, por exemplo, para aumentar ou reduzir a dificuldade do jogo para que ele seja recompensador e forneça o nível de complexidade que você deseja. Com alavancas de design, você pode testar e ajustar repetidamente até obter o resultado desejado.
As alavancas de design podem ser usadas nos estágios de conceito e protótipo do desenvolvimento do jogo, até o polimento pós-produção. Christo diz que acrescenta alavancas de design quando mapeia suas ideias em um diagrama de fluxo. Tente pensar logo no início do seu projeto sobre quais interruptores e alavancas seu sistema precisa para que você possa ajustá-lo e explorar possibilidades de jogabilidade sem depender muito da refatoração de código mais tarde.
A imagem a seguir é de um gráfico que representa uma jogabilidade simples, onde os inimigos estão no local no início, e o jogador entra armado e armado. Basicamente, eles precisam matar inimigos, mas ao manipular as alavancas de design você pode mudar o foco da jogabilidade. Em uma configuração, a jogabilidade é centrada em pontuações altas e na matança rápida de muitos inimigos dentro do limite de tempo, enquanto em outra, a ênfase está em matar uma quantidade definida de inimigos em um tempo menor, dando tempo para os jogadores pegarem os itens perdidos antes de serem extraídos.

Este sistema também pode ser usado para criar uma tempestade de balas completa com excelentes quedas e diferentes tipos de munição com suas próprias propriedades. Ao adicionar mais alavancas de design, como um tempo limite para o respawn, você pode estender o sistema ainda mais.
Escape from Tarkov da Battlestate Games fornece outro bom exemplo de design de jogo sistêmico no Unity. O jogo tem um sistema de criação para criar uma arma com seu próprio conjunto de dados, como pode ser visto na imagem abaixo. Esse conjunto de dados afeta as características da arma e a jogabilidade geral, de forma semelhante à saúde do jogador. Se o jogador sofrer uma fratura ou ficar doente, sua arma se tornará mais difícil de usar, enquanto um jogador saudável terá melhor controle sobre a arma.

A relação entre um sistema, armas, e o outro, saúde, incentiva o jogador a valorizar não apenas sua vida, mas também armas de melhor desempenho. Ninguém quer um AK sem proteção contra poeira ou com a coronha balançando enquanto erra tiro após tiro, um sinal claro de que a arma é uma má opção em sua configuração atual.
Há também uma grande seleção de tipos de munição que têm propriedades diferentes, assim como de blindagem. O tipo de munição e armadura do seu oponente determina em que parte do corpo você deve atirar para causar mais dano, criando uma jogabilidade meta. Esses sistemas, cada um com seu conjunto de dicas visuais, são equilibrados para criar a “essência” de jogabilidade que seus designers estavam procurando.

Uma maneira de configurar alavancas de design no Unity é com ScriptableObjects. Eles podem ser usados como contêineres de dados que são salvos como ativos e referenciados a partir de scripts sem criar dependências para outros objetos em uma Cena.
Você pode criar vários ativos ScriptableObject que contêm diferentes conjuntos de valores que você pode compartilhar e trocar para alterar seções inteiras do jogo, de forma semelhante às predefinições. Suas alterações são salvas no Modo de Reprodução com ScriptableObjects, então, quando você sair, não precisará retornar a nenhuma nota e implementar alterações.
Por exemplo, ao criar o protótipo de um personagem, você pode alterar a aparência do personagem substituindo o ativo ScriptableObject por um que contenha um conjunto diferente de valores. Esta é uma porta de entrada potencial para prototipar buffs e debuffs ou conectar a seleção de personagens aos perfis.
Digamos que você esteja criando um jogo de tiro e implementou um sistema de armas com valores arbitrários para ações como recuo, cadência de tiro, precisão, modos de tiro, configurações de áudio, configurações de efeitos visuais e assim por diante. Você pode criar quantos perfis de armas quiser e ajustar suas configurações no Modo de Jogo, onde suas alterações são salvas, tudo de uma vez. Você também pode enviar esses ScriptableObjects predefinidos para os membros da sua equipe e recebê-los para receber feedback, o que é útil quando você está tentando encontrar a sensação certa para a jogabilidade.
As alavancas de design podem substituir variáveis únicas no código como propriedades públicas e podem ser limitadas por seu intervalo usando o RangeAttributedo Unity, que limita os valores flutuantes ou inteiros no seu script a um determinado intervalo, ao mesmo tempo em que permite que sejam exibidos como controles deslizantes no Inspetor. A intenção é manipular as alavancas rapidamente, não apenas no Modo de Reprodução, então também é aplicável se você estiver executando no Modo de Edição ou testando uma ferramenta.

Em jogos de sobrevivência, entre outros gêneros, um jogador espera uma gama de escolhas que resultem em consequências lógicas e razoáveis, levando-o a encontrar uma solução para cada desafio. Como você poderia projetar um sistema para que tanto os desafios quanto as soluções fossem, até certo ponto, resultado da emergência?
Vejamos um exemplo em que o jogador precisa permanecer em uma área para sobreviver, como no jogo Don't Starve do estúdio Klei. O jogador pode ficar perto do fogo para evitar que o inimigo ataque. O fogo também pode ser usado para cozinhar alimentos e manter os jogadores aquecidos. Entretanto, se o fogo chegar muito perto do jogador, da comida ou de objetos inflamáveis, ele os queimará.
Que tipo de sistema é necessário para criar reações em cadeia como a descrita acima? Você pode simplesmente criar um Volume para o jogador ficar, o que lhe dará calor ao longo do tempo, ou fazer uma propagação de fogo linear como um sistema. Mas por que não abordar isso com uma lente de designer mais centrada no sistema? Você quer obrigar o jogador a reagir em uma situação que é o resultado de uma reação em cadeia de sistemas individuais de propagação de fogo colidindo entre si e com outros sistemas que existem no mundo do jogo.

Você poderia ter um sistema no qual as árvores crescem em uma área definida de terreno ao redor de um lago ao longo do tempo. Essas árvores brotarão e crescerão até que o limite de espaço seja atingido. Quando maduras, as árvores podem ser cortadas e transformadas em madeira, que, claro, também é inflamável.
O jogador pode usar essa madeira para construir itens, como uma cadeira de madeira elegante, ou fazer uma pequena fogueira com ela perto do lago para se aquecer e secar depois de um mergulho. Mas o que acontece se você der ao jogador a habilidade de acender a fogueira?
O sistema inflamável na madeira não é complexo, mas se algo estiver pegando fogo, ele emite calor em um raio, e se esse valor de calor estiver acima do limite do item de madeira ou árvore próxima, essas coisas também pegarão fogo (propagação simples). Assim, o jogador, ao acender sua fogueira, ateou fogo em sua bela cadeira de madeira. Agora o jogador precisa pegar a cadeira e jogá-la na água para apagar o fogo, mas enquanto faz isso, a fogueira incendeia a árvore mais próxima, e agora você tem um incêndio florestal em suas mãos.
Mesmo um sistema pequeno e contido como este exemplo pode criar experiências divertidas e “sem roteiro” para os jogadores. Além disso, é essencial manter o foco no resultado desejado para o jogador, em vez de em um design muito ligado à realidade, o que lhe dará menos capacidade de criar resultados inesperados.
Neste exemplo, no Unity, você pode criar possibilidades emergentes armazenando suas alavancas de design em um ScriptableObject colocado em qualquer coisa que você queira que pegue fogo. Vamos começar observando a madeira em um mundo onde uma árvore morta já está pegando fogo perto da beira da água, mas está inclinada em direção à água, e nosso jogador precisa se aquecer.
Neste exemplo, a madeira tem um ScriptableObject com vários valores.


Vamos analisar esses valores com mais detalhes:
- Temperatura padrão: Um valor de espaço reservado, se não houver nada a herdar de um estado global. Se forem altas ou baixas globalmente, podemos impactar a sensação de todo o sistema, pois temperaturas mais altas podem criar um incêndio florestal, supondo que todas as árvores usem o sistema de propagação do fogo.
- Temperatura atual: A temperatura de um item à medida que ele esquenta ou esfria, o que determina se um item queimou ou não (se o valor da temperatura atual estiver acima do valor da resistência)
- Temperatura de combustão: A temperatura que um item deve atingir antes de pegar fogo
- Taxa de aquecimento: Quão rápido o item aquece quando está no raio de outra fonte de calor
- Taxa de Recarga: Quão rápido o item retorna à sua temperatura “não aquecida”, o que pode ser chamado de retenção ou qualidade térmica, desde que o nome da alavanca de design seja autodescritivo
- Taxa de queima: Quão rápido o item queimará ao longo do tempo
- Combustível: Quanto combustível o item tem ao queimar
- Resistência ao calor: A força do calor dentro do raio
- Raio de calor: Alcance ou extensão do calor
Com algum código de jogo de suporte, você pode ter um objeto próximo a outro pegando fogo. Você pode armazenar perfis dos seus protótipos e tentar configurações totalmente diferentes até encontrar os pontos de ruptura e, então, restringir esses valores com atributos.

Não há um projeto para que o fogo seja bloqueado pela água, mas se não houver nada inflamável na água, o fogo não se espalhará se não puder atingir o outro lado, a menos que você adicione um novo sistema.
Este exemplo de um sistema de propagação de fogo fornece várias maneiras de criar o mesmo resultado brincando com o combustível, a taxa de queima e a intensidade do calor. E você pode criar novos resultados, por exemplo, substituindo combustível por “saúde”, para obter um alcance constante para controlar quando uma árvore cai sem perder a funcionalidade. Quando uma árvore atinge baixa saúde, ela terá uma alta probabilidade de cair. Agora, quando uma árvore em chamas atinge pouca saúde, ela pode cair, criando um caos absoluto quando deixada sem controle pelo jogador em uma área de objetos combustíveis.
À medida que você começar a adicionar mais sistemas ao seu ambiente, você criará um ecossistema de sistemas que podem reagir entre si. Supondo que o jogador consiga coletar, construir e fabricar itens com madeira e que todos herdem nosso sistema de propagação de fogo, o caos pode estar próximo se você não tomar cuidado!

Você pode criar uma configuração de propagação de fogo altamente volátil reduzindo o Limiar de Combustão e aumentando a Taxa de Aquecimento para que os objetos queimem mais rapidamente. Aumente o raio para obter uma propagação mais rápida e incontrolável. A taxa de aquecimento é limitada de 0 a 50 para fornecer granularidade; a intensidade do calor pode ser usada para multiplicar esse valor, mas você deve mantê-lo dentro de uma faixa razoável. Uma Força Térmica de 4 expandirá a Taxa de Aquecimento para uma faixa de 0 a 200, o que é um exagero e resultaria em um incêndio florestal em poucos segundos. Como o jogador não terá tempo de reagir para controlar o fogo, não é uma ótima experiência de jogo.

Aumentar o Limiar de Combustão para 300 proporciona um sistema de propagação de fogo mais equilibrado. O jogador pode realizar outras tarefas antes que um incêndio comece e, quando isso acontecer, ele terá tempo para reagir e controlá-lo se for rápido. Especialmente se eles tiverem a capacidade de cortar árvores, construir barreiras ou tiverem acesso a um sistema de água igualmente sistêmico e simples.
Você pode estender ainda mais o sistema de propagação de fogo introduzindo um valor de resistência para objetos dentro do raio de calor do fogo. Isso permitiria que você tivesse incêndios de temperaturas variadas ou introduzisse revestimentos resistentes ao fogo em estruturas como uma possível atualização. Provavelmente é um exagero, mas é um exemplo de como pensar no design de jogabilidade de uma maneira sistemática que pode dar ao jogador mais possibilidades de sobreviver e prosperar em um ambiente de floresta fria ao interagir com o sistema de fogo.

O exemplo dos sistemas de propagação de fogo mostra como você pode pegar uma ideia de mecânica linear e transformá-la em uma experiência interessante que permite ao jogador resolver desafios por meio do aprendizado e da compreensão dos sistemas do jogo. E quando seu sistema não precisa imitar a realidade, você não precisa acomodar complexidade e abstrações adicionais.
Com este exemplo simples, esta postagem explora como você pode projetar sistemas modulares, pequenos e simples com interatividade que criem um ecossistema maior para a jogabilidade, que pode ser equilibrado com alavancas de design que você pode ajustar e iterar com a contribuição de seus colegas. Esses elementos podem criar momentos inesperados de diversão, prazer e suspense para seus jogadores, ajudando a tornar seu jogo uma experiência verdadeiramente única.
Obtenha muito mais dicas, instruções e inspiração para projetar e aprimorar a jogabilidade no Unity em nosso novo e-book disponível gratuitamente.
