Em sua palestra, ele prestou atenção ao princípio básico de construção de muitos efeitos no jogo, ou o princípio da granularidade. Como o estúdio implementou um sistema em grande escala de destrutibilidade realista, quais limitações de seus próprios recursos e desempenho da plataforma enfrentou, quais otimizações fez e quais lições aprendeu com tudo isso - mais adiante no material.
Então, primeiro sobre os desafios que o estúdio enfrentou.
O jogo se passa dentro de um prédio de agência governamental de estilo brutalista que tem algumas características sobrenaturais, como paredes móveis.
A estrutura da sede tinha que parecer verossímil, porque se trata de um órgão do governo, onde milhares de funcionários de serviço trabalham em atribuições de rotina. Mesas, telefones, canecas, multifuncionais - todos esses são os atributos usuais de um funcionário de escritório que você espera ver no local de trabalho e, com sua presença, ajudam a contar qualitativamente a história deste mesmo lugar. Brutalismo significa toneladas de concreto, mas não só: aqui temos madeira e vidro, que criam o visual mais adequado para um prédio de serviços especiais.
Quando se trata de destruição, a primeira coisa a se pensar é a tatilidade. A equipe de desenvolvimento foi encarregada de organizar um rico ambiente interativo que imediatamente cria a sensação de poder interagir com quase tudo dentro dele.
Obviamente, o estúdio enfrentou certas restrições durante seu trabalho. As interações com os objetos devem parecer e parecer realistas. O jogador deve ter alguma liberdade de ação em relação à destruição, mas não ilimitada, já que as possibilidades do jogo dependem do desempenho máximo das plataformas, memória e requisitos de inteligência artificial. Ao mesmo tempo, a equipa encarregada da implementação do ambiente destrutível revelou-se bastante reduzida, o que também teve de ser tida em consideração nos trabalhos.
Portanto, a destrutibilidade no jogo é baseada no princípio da granularidade. É também a base para muitos efeitos especiais na cinematografia. Seu significado é que a natureza não é quantificada. É uma tela contínua criada a partir de uma ampla gama de objetos - de grandes a pequenos, de sólidos maciços a poeira e fumaça. Se algo não for refletido na tela, a imagem inteira não funcionará.
Em um motor de jogo, esse princípio pode ser implementado em três níveis diferentes de detalhes. Os objetos sobre eles são apresentados na forma de corpos rígidos (Rigid Bodies), suas partes, partes de adereços, próprios adereços e o ambiente. O último, neste caso, é um tipo de grade estática com a qual os objetos interativos podem colidir. Partículas de malha, hierarquia sólida e decalques de material fornecem aos objetos mais detalhes em certas camadas. Assim, de objetos sólidos passamos para seus fragmentos e depois para fragmentos. A última camada são as próprias partículas. Sprites de partículas, partículas de brasa, areia e muito mais, todos desempenham um grande papel no preenchimento desses gradientes.
A imagem acima mostra um ambiente estático. Parece muito vazio, embora haja alguns detalhes aqui: por exemplo, ao fundo você pode ver o corrimão da escada.
É incrível como a percepção muda quando começamos a preencher o espaço com objetos com os quais podemos interagir diretamente.
Quanto ao fluxo de trabalho no Remedy, é realmente muito trivial. Os artistas do ambiente fornecem módulos de geometria nivelada e adereços para a montagem, após o que o departamento de efeitos visuais configura as plataformas e as animações de destruição cinematográfica. Finalmente, o resultado é enviado para o motor do próprio Remedy, Northlight.
Era preciso definir uma abordagem de como tudo funcionaria, e a equipe estabeleceu uma abordagem processual.
O que isso significa?
A abordagem processual é baseada em regras de processamento e interpretação de dados.
As informações sobre o mundo do jogo são representadas por modelos contendo metadados sobre os materiais. Então, você pode definir, por exemplo, que os assentos da bancada são de tecido, a base é de concreto, as plantas são na verdade plantas. Definidos os materiais, você pode formular um conjunto finito de regras para cada um deles, determinando as reações a todas as ações que podem ser realizadas no jogo. Por exemplo, ao disparar das plantas, pedaços de folhas voam, o concreto se quebra e o tubo de metal se deforma e a água explode dele. Em seguida, todos os dados são redirecionados para o mecanismo e ele já reage a cada interação conforme apropriado.
Então, por que destruição processual?
Porque havia a necessidade de uma mudança rápida e consistente de ações, comportamento previsível dentro de condições claramente definidas. Existem centenas de ativos envolvidos no jogo. Na imagem acima, você pode ver todos os tipos de blocos que compõem salas, paredes, colunas, escadas, grades e muito mais. Embaixo dele estão vários acessórios: mesas, cadeiras, vasos, plantas, computadores, telefones. Para implementar a destruição de uma variedade de objetos, uma equipe de apenas 1-3 pessoas foi selecionada. Para tanto, foi necessário predeterminar os padrões segundo os quais o mundo funciona: se um objeto é influenciado de certa forma, é necessário que ele se quebre exatamente como está prescrito para o método escolhido de destruição de um dado material.
Então, foi necessário definir um determinado comportamento dependendo do material. Para que, quando você atirar na árvore, ela voe em pedaços. Ou, se você atirar em um vidro, ele se estilhaçaria em cacos. Ao mesmo tempo, as partículas e os decalques também devem se comportar de uma determinada maneira de acordo com a composição do objeto.
Cada material possui sua própria geometria de fratura, definida por diferentes níveis. No exemplo, vemos um pedaço de guarda-corpo, na base do qual está concreto, depois um suporte de metal e, por último, madeira. Da esquerda para a direita, os estágios são mostrados à medida que se quebram:
- O nível A mostra uma ruptura no concreto. Não há decalques aqui, pois ainda há poucas rachaduras. Percebe-se que o suporte está ligeiramente dobrado.
- Nível B. O metal se foi, mas ainda há mais concreto e madeira quebrados.
- C : , .
Agora vamos imaginar que batemos em um determinado canto de um objeto - então ele não deve quebrar completamente, apenas parte dele.
Portanto, em Control existem corpos sólidos que são um único objeto. Mas também há detalhes conectados por links. Esses são os mesmos corpos rígidos que uma chamada colisão composta pode separar.
As peças são criadas durante a inicialização, compartilham um colisor comum e se movem como uma única peça até que se quebrem. Eles estão conectados uns aos outros por aquelas superfícies que se tocam.
Vamos falar sobre conexões. Eles são criados em uma hierarquia geométrica baseada em metadados. Os sólidos são ligados entre si por uma espécie de dobradiça - por exemplo, no caso de uma porta ou gaveta. Eles podem ser destruídos dinamicamente, novamente pela força do impulso.
Existe uma física especial de destruição para compostos. Eles não se rompem com o objeto - ou seja, se você fizer um furo na porta, a porta continuará sendo um objeto inteiro, mantido unido por conexões internas. Assim, se você quebrar o bloco pai RB1, a porta não cairá das dobradiças: um pedaço dela ainda ficará preso à abertura, não sendo afetado pelo impacto. E uma porta com um buraco no meio ainda pode ser fechada e aberta como esperado. Assim, os desenvolvedores queriam evitar situações em que os objetos se quebrassem completamente, independente de onde e com que força o golpe caísse, como é o caso de alguns jogos.
A simulação proprietária do Northlight executa a lógica de destruição e determina quais eventos e partículas reagem a ela. O motor de física da NVIDIA então modela os corpos rígidos e tenta encaixá-los nas restrições do jogo.
A própria destruição é realizada da seguinte maneira. Temos alguma geometria de entrada. Às vezes é necessário pré-preparar o modelo, definir a geometria de ligação e determinar em quais casos quais peças podem quebrar. Os modelos são então enviados para Houdini e processados lá. Destruição em Houdini é uma configuração HDA em grande escala que realiza reações baseadas em materiais e grava dados na memória. Às vezes, eu precisava consertar e definir manualmente alguns metadados de física para garantir que as configurações estavam corretas, especialmente quando se tratava de conexões. Em seguida, todos os dados são transferidos para o motor, onde são usados para criar o mundo do jogo.
A ferramenta de destruição em Houdini se parece com isso. Digamos que temos um bloco de concreto como entrada. É necessário determinar quais áreas podem quebrar e endurecer o material. Neste caso, o bloco irá realizar a destruição de acordo com as regras definidas para o concreto, controlá-lo e criar diferentes hierarquias em termos de geometria de renderização e colisões. Em seguida, você precisa se certificar de que a modelagem seja feita dentro do orçamento e estilo que você definiu. Depois disso, você pode exportar o modelo para o mecanismo.
É assim no motor. Você tem um tipo de hierarquia que carrega informações sobre as camadas A, B, C, etc. Isso inclui o nome do material, se o objeto é estático ou não, dados sobre conexões, seus tipos e assim por diante. A hierarquia é representada por níveis e as propriedades físicas diferem dependendo do nome do material. Se o nome for especificado corretamente, a física é processada pelo mecanismo. Falaremos sobre o problema dos nomes mais tarde.
Acima está um cenário de simulação de corpo rígido. Jesse atira objetos ao seu redor, e eles explodem, realizando assim a física da destruição.
Como um ambiente destrutível exige muitos recursos e os consoles e PCs têm seus próprios limites de desempenho, a equipe se deparou com a tarefa de otimizar o sistema para que não sobrecarregasse os dispositivos.
Uma vez que era necessário caber em um determinado orçamento de desempenho, um limite foi definido em 200 sólidos ativos na tela - então os objetos fora dela desapareceram completamente.
No caso de eventos envolvendo muitos objetos em movimento rápido, há um atraso nas colisões para que o sistema tenha tempo de fazer todos os cálculos.
O modo de suspensão também foi implementado para itens não utilizados. Por exemplo, se um bloco de concreto cai no chão, ninguém espera que ele comece a pular como uma bola - então ele pode "adormecer" rapidamente. Isso se aplica a muitos itens do jogo. Pelo mesmo motivo, podem ser empilhados uns sobre os outros e, da mesma forma, ficarão imóveis.
Além disso, as lacunas entre os itens foram preenchidas com partículas. Assim, quando um objeto é destruído, poeira ou lascas são formadas ao seu redor.
Tudo no jogo é sistemático e baseado em eventos. Existem os seguintes eventos de partículas:
- impacto de bala, que tem um resultado diferente dependendo do material;
- quebrar a conexão entre duas partes; neste caso, ocorre o sucateamento, liberando partículas;
- destruição completa de um objeto, levando à sua desintegração em partículas.
O acima mostra o processo de edição de partículas. No jogo, você pode colocar um determinado sistema de partículas e depois alterá-lo. Nesse caso, a frequência da formação da centelha simplesmente muda. Curiosamente, você pode alterá-lo literalmente em tempo real e obter imediatamente uma resposta instantânea e, em seguida, reproduzi-lo novamente e ver como o efeito funciona. Implementado dessa forma, um loop de iteração rápida permite que você aprimore coisas como essa até que sejam exibidas corretamente.
Outra característica das partículas é a modelagem padrão. De vez em quando, a equipe precisava usar campos de distância sinalizados (SDF). Graças a isso, foi possível garantir que objetos não caíssem no chão, o que ficaria extremamente estranho.
No exemplo acima, um objeto destrutível é uma simbiose de partículas e um sólido. Isso é o que vemos. A explosão cria poeira no ar devido a camadas adicionais de partículas que preenchem as lacunas que faltam no gradiente de granularidade.
E o último - decalques de materiais, dos quais existem muitos no jogo e eles são gerados dinamicamente. Basicamente, são apenas texturas aplicadas sobre objetos para criar a aparência de destruição.
Se algo quebrar, um decalque rachado aparecerá no item. Eles geralmente são criados em Houdini ou similar. No Controle, a escolha do decalque desejado é feita de forma dinâmica com base no material. Também ajudou a fazer uso de uma parte bastante grande da geometria estática. Como foi mostrado no início, sempre existem muitos objetos estáticos ao nosso redor, que também podem estar sujeitos a algum tipo de influência que deve ser levada em consideração.
Isto é o que parece. Se você quebrar o chão, o polígono em si permanecerá o mesmo, mas com a aparência dos decalques, sua aparência pode mudar muito. É importante notar que eles são bastante econômicos e eficazes no uso.
Portanto, temos partículas, sólidos e decalques. Neste exemplo, tive que fazer alguns truques, porque uma ferramenta de explosão simples não geraria tantos decalques. Agora Jesse "atira" um objeto que pode deixar uma marca no chão. Ao mesmo tempo, o piso permanece um polígono estático, mas graças aos decalques, as marcas de impacto permanecem nele.
Vamos também tocar no tópico de adereços personalizados. Existem muitos itens no jogo que podem ser espalhados - extintores de incêndio, computadores, lâmpadas e outros - que não podem ser gerados de maneira totalmente processual. Os artistas do ambiente ainda tiveram que definir manualmente os efeitos para cada um deles. No entanto, pela presença deles, o mundo do jogo parece apenas mais rico e diversificado.
Então, quais lições o estúdio aprendeu com o Controle?
Vale a pena abordar as seguintes coisas:
- ;
- ;
- ;
- .
O primeiro é a qualidade da geometria. Uma geometria de entrada inconsistente pode resultar de dimensionamento e orientação incorretos, mas também de atribuições de material incorretas. Às vezes, a qualidade da malha pode ser muito baixa e isso também terá um efeito prejudicial no resultado. Também acontece que quando você quebra um objeto, você percebe que não há nada dentro dele, e isso está errado. Para evitar tais problemas, é necessário aprimorar os dados de entrada, padronizar todo o pipeline de geometria para que, ao exportar, o sistema avise se algo não atende aos critérios e precisa ser corrigido. Isso ajudaria a evitar ciclos de feedback constantes entre departamentos diferentes, procurando exatamente quando os problemas surgiram.
Além disso, seria bom ter ferramentas integradas para que você possa modelar um objeto e ver imediatamente como ficará quando destruído. Obviamente, isso representa o desafio de fazer mais ferramentas com interfaces melhores, mas vale a pena.
Estamos acostumados a dar nomes a coisas diferentes. Mas o problema é que esses nomes podem estar incorretos. Por exemplo, Controle tem 17 designações diferentes para o material "concreto", e você não pode culpar ninguém por isso, porque sempre há um fator humano. O conselho de Richter é abandonar completamente o padrão de nomenclatura. Melhor ter apenas uma única API de metadados. Dessa forma, independentemente da ferramenta que os artistas utilizem para criar os adereços, é possível exportar dados para o motor direto de lá, sem etapas intermediárias.
O próximo tutorial é principalmente específico para Houdini. O ponto principal é que, muitas vezes, ao começar a trabalhar em algo, você o refaz muitas vezes no processo, faz alguns complementos e precisa ter certeza de que mesmo após dois anos de trabalho você pode abrir o arquivo de origem que a ferramenta de trabalho já poderia ter mudado 20 vezes. Isso significa que você precisa de algum tipo de padronização para trabalhar com HDA. É nisso que a Remedy está trabalhando agora: garantir que tudo seja distribuído corretamente, para que você nunca perca nenhuma versão da ferramenta e sempre tenha a oportunidade de repetir o que fez no passado.
É importante observar aqui que, ao criar ferramentas automatizadas, você está, na verdade, usando o mesmo software como se estivesse fazendo tudo manualmente. E, desde que tenham o mesmo back-end, tudo deve ser completamente consistente.
Desempenho e teste são alguns dos aspectos mais essenciais do desenvolvimento.
Os testes não foram automatizados no Remedy inicialmente. Após adicionar novos objetos ao nível, era necessário percorrê-lo manualmente para verificar se tudo estava funcionando corretamente. Mas então algo mudou no motor, o back-end mudou, algo foi otimizado e, depois disso, foi necessário um novo teste. Isso é muito perigoso, porque você certamente se esquecerá de verificar algo. Resumindo, não é a melhor maneira, levando a um potencial acúmulo de bugs.
O segundo aspecto é o teste de desempenho. Por um longo tempo, o Remedy não mediu nenhuma métrica significativa, como taxa de quadros ou tempo de computação. Portanto, os problemas de desempenho geralmente eram descobertos tarde demais.
O que pode ser feito aqui é, antes de tudo, melhorar os indicadores de desempenho. É necessário determinar quais o aumento dos parâmetros afetarão melhor ou pior o jogo, para contar com isso na hora de otimizar e determinar um orçamento que não pode ser ultrapassado.
Além disso, o teste automatizado pode ajudá-lo, dentro do qual você também pode variar a saída para demonstrar melhor o impacto das alterações no mecanismo.
Você também pode identificar e agir contra a degradação do desempenho. Por exemplo, para fazer com que, durante eventos de grande escala, alguns objetos contornem níveis intermediários de destruição - digamos, de sólidos indo diretamente para partículas.
Outra medida é o zoneamento da área em função da carga prevista. Esta ideia baseia-se no facto de podermos determinar nós próprios a que área aplicar certas contramedidas para não aplicá-las a todos os ativos ao nível quando não é necessário. Por exemplo, se logo inimigos com granadas chegarem a tempo de Jesse, obviamente haverá muita destruição no local, e durante o ataque, o processo de geração de destruição pode ser acelerado.
Como resultado, gostaria de observar que a equipe Remedy fez um trabalho monumental, do qual você pode obter muitas idéias em termos de implementação e otimização do sistema de destruição processual do ambiente.