Como ECS, C # Job System e SRP alteram a arquitetura

Trabalhamos com o Unity há muito tempo e não pudemos deixar de convidar o pessoal deles para o Pixonic DevGAMM Talks, que foi em setembro. O engenheiro de campo Valentin Simonov contou como planejar a arquitetura dos jogos, levando em consideração as vantagens das novas tecnologias. A Unity trabalha neles há vários anos para alcançar um nível de desempenho anteriormente inatingível. Você pode ouvir a apresentação no YouTube e ler a transcrição com slides logo abaixo do recorte.


E se eu disser que você pode aumentar a produtividade do seu jogo em 10 vezes? De fato, isso não é inteiramente verdade, mas há alguma verdade em toda piada. Quero falar sobre o que estamos trabalhando agora, qual será o futuro do Unity e o que você pode usar agora.

Unidade faz jogos completamente diferentes. Aqui estão alguns exemplos que eu mesmo interpreto. Eles usam recursos diferentes e precisam de desempenho diferente, uma abordagem diferente para o desenvolvimento.



E estamos trabalhando em um projeto que chamamos de desempenho por padrão. Esses são alguns recursos especiais que, se usados ​​corretamente, obterão um aumento significativo no desempenho. Em algumas tarefas, medimos x10 e até x11. Especialmente nos problemas de simulação de um grande número de objetos que interagem entre si.

Mas quando falamos de Perfomance por padrão, queremos dizer que você terá que mudar a abordagem do desenvolvimento, alterar muito a abordagem da arquitetura dos jogos. E, de fato, nem todo mundo precisa disso.

Uma pergunta popular: “O que você está fazendo no seu ECS? Você remove todo o GameObject, remove toda a transformação, hierarquia e componentes? ” Não, todos nós deixamos. Você pode trabalhar com o Unity exatamente da mesma maneira que está agora, mas se quiser mais desempenho, precisará conhecer as tecnologias sobre as quais quero falar brevemente.

E quero mencionar outra tecnologia chamada Scriptable Render Pipelines (SRP) - ela permite que você escreva com mais eficiência um pipeline de renderização para o seu jogo. Você provavelmente viu a demonstração que mostramos em um dos Unite. Aqui no PC em tempo real, um número gigante de unidades é simulado, algo em torno de 60 mil (atinge 100 mil e começa a desacelerar um pouco):


E os novos recursos sobre os quais quero falar são: Sistema de componentes de entidades (ECS), Sistema de tarefas em C #, nosso novo supercompilador Burst e Pipelines de renderização de scripts (SRP).



Repito: cabe a você escolher se quer ir em frente conosco, aprender novas tecnologias ou se está bem em desenvolver jogos que ganham dinheiro bem e são simplesmente criados.

Para entender o que estamos tentando resolver, é importante entender o estado do ferro em 2018.



Observe como o desempenho e o número de núcleos da CPU estão aumentando. De um ponto, o desempenho de thread único caiu. Ou seja, agora temos muitos núcleos, mas sua produtividade não está crescendo tão rápido. Portanto, gostaríamos de usar o poder de todos os núcleos.



Meu telefone possui 8 núcleos: 4 fortes e 4 fracos. E um telefone moderno pode funcionar tão rápido quanto um computador moderno (mas não por muito tempo devido ao superaquecimento). Você também precisa entender que aumentar o desempenho não é apenas usar todos os núcleos, mas também otimizar o desempenho de núcleo único.

E a última imagem, que sempre damos como exemplo de como o desempenho do processo aumenta e a velocidade de acesso à memória não aumenta muito:



Pode-se ver que agora o acesso à memória é extremamente lento. Os fabricantes de processadores fazem muito para nivelar essa diferença - adicione caches, as CPUs estão envolvidas em cálculos especulativos, tentando prever qual código será executado a seguir. E se você não pensa nisso quando cria seu jogo (ou quando criamos um mecanismo para você), não podemos tirar o máximo proveito dos processadores modernos.

Muitos de vocês provavelmente passam horas olhando para uma imagem semelhante no Unity:



Aqui você pode ver que há multithreading, mas os núcleos e threads restantes geralmente não estão ocupados. Algo está sendo feito, mas eu gostaria de ocupá-los completamente.

Agora temos a renderização, essa é uma caixa preta. Você tem uma opção: Encaminhar ou Adiar, além de várias configurações de materiais, shaders, Buffers de Comando e assim por diante. Você pode criar uma imagem bonita, mas muitos algoritmos são extremamente difíceis de implementar.



E todos sabemos sobre arquitetura no Unity: componentes, GameObjects, hierarquia de transformações, todo o código, todos os dados no MonoBehaviour e cada componente processa seus dados.



Mas há problemas com o estado atual das coisas. Mais cedo ou mais tarde, você se depara com isso e entende como precisa e não precisa. A hierarquia de objetos em si tem uma certa sobrecarga e algumas entidades não precisam ser GameObjects. E se você tiver um grande número de componentes e atualizações, tudo ficará muito mais lento. Certa vez, escrevi este artigo , que ainda é relevante se você quiser saber como não fazê-lo.



E o mais importante no contexto dos processadores é que todos os componentes, todos os dados estão espalhados na memória, o que interrompe o uso do cache do processador.

Agora eu quero passar rapidamente por novos recursos.



Não vou me concentrar muito no que é o ECS e como ele funciona. O ponto é que temos Entidade, que é apenas o ID de certas entidades no jogo - elas armazenam dados na forma de componentes, ou seja, apenas dados, sem código. E os sistemas processam a Entidade com determinados componentes e, de alguma forma, alteram esses dados.

Por que estamos fazendo nosso ECS e como será melhor que os concorrentes? Existem alguns pontos. Primeiro, não oficialmente, mas achamos que faríamos o motor agora. É claro que não queremos nos livrar do GameObjects, os componentes atuais do Unity, jogar completamente tudo fora e instalar o ECS. Mas queremos avançar em direção a um motor melhor.



Contamos com alto desempenho. Não faz muito tempo, Mike Acton se juntou a nós (se você está em desenvolvimento em C ++, sabe que ele é um dos evangelistas da Programação Orientada a Dados). E queremos fazer com que todo o sistema funcione o mais rápido possível - mais rápido que o C ++.

Também pensamos em como integrar coisas diferentes nativamente no ECS. Há algum tempo, anunciamos que estávamos criando uma nova rede e ela também é baseada no ECS - será possível criar um jogo multiplayer no ECS e compartilhar código entre o cliente e o servidor.

Trabalhando em ferramentas de depuração no Unity. I.e. enquanto o ECS existe, por assim dizer, separadamente do GameObjects e componentes, e isso é muito inconveniente. Queremos simplificar as coisas.

Agora há um DebugView que se parece com isso:



Aqui você pode ver que tipo de Entidade você tem, quais sistemas quanto tempo leva para processar, quais sistemas funcionam com quais componentes e para cada componente você pode ver no inspetor, quais dados cada Entidade possui nos componentes (observe que a API geralmente muda e muitos Os tutoriais já podem estar desatualizados).

Além disso, se você ouviu falar sobre o nosso novo desenvolvimento Unity for Small Things (este é um tempo de execução muito pequeno que permite criar jogos para mensageiros instantâneos) - tudo também é construído no ECS lá.

Recentemente, o boom de desenvolvimento e transição para o ECS é uma tecnologia muito popular e todos precisam conhecê-la.

Temos uma conferência para programadores, por isso é difícil ficar sem um slide de código. Há muito código lá, então é difícil extrair algum tipo de peça inteligível para deixar algo claro.



Na verdade, peguei um sistema no exemplo que funciona com o C # Job System (mais sobre isso mais tarde) e fazemos muito para reduzir a quantidade de código, adicione uma sintaxe shugar.

Existe um sistema que funciona com os componentes RotationData e também precisa das transformações GameObject, representadas por um TransformAccessArray especial. E todas as atualizações do sistema que criamos Job, executamos este Job, ele é atualizado em algum lugar, podem ser divididas em vários grupos e executadas em threads diferentes.

Como usar no projeto? Assim como em outras implementações do ECS, você precisa entender que precisa pensar de uma maneira completamente diferente (diferente dos GameObjects e Transforms). E se acostume com essa ideia. É claro que você precisa começar desde o início do projeto, porque muitas vezes recebo perguntas como "fizemos o jogo e queremos mudar para o ECS - como?". No jogo final, isso é muito difícil de fazer.



Precisamos pensar na interação com o Unity, já que o ECS vive separadamente, em seu pequeno mundo. Damos algumas oportunidades de interação com GameObjects e Transforms, mas com física, renderização etc., aqui fica cada vez mais complicado. E enquanto você precisa aturar o fato de que grande parte da interface familiar não estará disponível, mas também estamos trabalhando nisso.

E imediatamente você precisa pensar no fato de escrever sistemas no Job System, o que é muito mais eficiente.



Algumas palavras sobre o Job System. Queremos criar uma maneira muito simples de escrever código multiencadeado. Ao mesmo tempo, escreva em C #, verifique tudo para você, não dê a oportunidade de cometer erros ou mostre por que, onde e como você os cometeu. Limitamos os recursos de idioma que você pode usar nos Trabalhos e chamamos esse subconjunto C # de Alto Desempenho C #. Você não tem referências no código do trabalho, nenhuma linha, todos os dados precisam ser copiados - você não pode usar um grande número de recursos de idioma, dificultando muito a gravação de vários segmentos na perna.

Também apresentamos coleções e integração muito rápidas com o ECS. Essa estrutura do ECS e do sistema de tarefas permite uma execução muito rápida do código.

Ao mesmo tempo, não apenas oferecemos a oportunidade de usar essas tecnologias - trabalhamos com esses sistemas e criamos novas APIs para que elas possam ser usadas nos trabalhos.



Criamos o Async Raycasts para a física, com o qual você pode dizer "Quero 600 rakecasts, faça isso comigo algum dia, por favor". Estamos trabalhando para garantir que, usando essas tecnologias, seja possível expandir os sistemas atuais, por exemplo, animação por meio da API do Playbles. E estamos pensando em criar novos sistemas no Unity que não serão fechados em C ++ e cujo código estará em C # e estará disponível para você.



Se você pegar o código de Jó, é bem simples. Job é uma estrutura na qual existe um método Execute, onde fazemos algum trabalho executando esse Job. Consequentemente, nosso Agendador interno algum dia entenderá onde é melhor executá-lo, resolverá todas as dependências. Aqui temos um JobHandle, que podemos usar como dependência para alguns outros trabalhos.

Como usar no projeto? É bom que você use Jobs desde o início, mas isso não é necessário aqui. Se você tiver algum tipo de sistema crítico de desempenho, por exemplo, simulação, busca de caminhos, rede ou algo mais - você pode descobrir como otimizá-lo com esta ferramenta.



Mas, para isso, você precisa dar alguns grandes passos, entender como armazenar dados corretamente. O ECS, de fato, nos permite armazenar dados corretamente, porque separamos os dados do código e nossa implementação do ECS armazena os dados dos componentes linearmente na memória e, executando esses componentes por algum sistema, você usa todos os recursos do processador, tudo é armazenado no cache e etc. Tentamos fazer isso muito rapidamente.

Em seguida, você divide esse trabalho em tarefas paralelas, escreve o código do trabalho e executa-o. E (provavelmente) tudo funciona para você. Obviamente, você precisa testar e, o mais importante, testar na plataforma de destino, dependendo do número de núcleos etc. Mas o uso do Job System e ECS, como eu disse, também afeta muito a maneira como você planeja sua arquitetura de jogos.

Então tudo é muito mais simples. O Burst Compiler é a nossa tecnologia exclusiva, um compilador especial dessa sub-rede C # (High Performance C #) no código da máquina da plataforma atual, que você publicará em seu projeto.



Os caras fizeram alguma mágica que provavelmente ninguém, exceto eles, entende, mas isso acelera o código do trabalho 10 vezes, o que é super legal. E o mais legal é que ele não requer nenhuma ação da sua parte - se você tiver um código de tarefa, basta adicionar o atributo [BurstCompile], a Burst compila seu código e obtém desempenho "gratuito". Esta é a nossa nova tecnologia e você pode experimentá-la agora.



E a última coisa que quero mencionar brevemente é o Scriptable Render Pipeline (SRP), no qual trabalhamos há muito tempo e que foi projetado para oferecer a você a oportunidade de escrever uma renderização muito personalizada para o seu jogo específico.



O Pipeline de renderização é um algoritmo que faz o descarte (quais objetos serão desenhados), renderização e pós-processamento. Agora temos uma caixa preta que Forward ou Adiada - eles já são bons, temos gráficos muito legais em telefones celulares, PCs e consoles. Mas eles têm muitas restrições, porque não podem ser expandidas. Usando esse novo recurso, SRP, você pode escrever seu Pipeline, remover algo de lá, adicionar, fazer o que quiser.



Atualmente, estamos trabalhando em dois exemplos de gasodutos. Um LWRP, direcionado para telefones celulares e dispositivos fracos, e HDRP, direcionado para PCs, consoles e nos quais pessoas famosas do setor trabalham. Antes disso, eles fizeram jogos AAA. Certamente, você viu nossa demo Book of the Dead.


Aqui usamos o HDRP para mostrar todo o poder dessa tecnologia.

Para usar isso, você também precisará executar um número bastante grande de etapas heróicas, porque com o novo Pipeline, quase nada é compatível com o que temos agora. I.e. se você atualizar com o Legacy, forneceremos um utilitário que atualizará a maioria dos materiais para você, mas você precisará reescrever seus shaders, ou seja, as texturas provavelmente parecerão diferentes.



Muito legal se você pode começar do zero e experimentar seu Pipeline. Se você quiser fazer algo no seu Pipeline, entre em contato conosco.

Novamente, entenda o que você precisa, porque agora você tem mais oportunidades de fazer algo, mas precisará de pessoas que possam fazê-lo ou precisará aprender como fazê-lo.



Na minha opinião, isso é legal, porque aqueles que nos acompanham com essas novas tecnologias terão mais demanda no mercado. É isso, espero que alguém olhe para essas tecnologias, crie jogos bonitos e divertidos.

Perguntas da platéia


- Quando posso obter o ECS e desenvolvê-lo?

- Você pode usar o ECS, o problema é que, na sua forma atual, é mais direcionado para pessoas focadas no desempenho, ou seja, algum tipo de projeto AAA. E a tarefa do Unity é disponibilizar o desempenho por padrão para todos. Portanto, precisamos de um determinado sistema, um complemento para o ECS, que nos permita usar o ECS com a mesma facilidade que usamos agora o MonoBehavior. Embora não exista esse complemento, não acho que o ECS será lançado em uma versão completa. E descobrimos que criamos um recurso que 1% de nossos usuários usarão. E isso não é uma tarefa da Unity. Conheço pessoas que já usam o ECS em produção, mas lembre-se de que esse recurso ainda está em desenvolvimento e agora estamos resolvendo a questão de como criar a interface mais conveniente. E a próxima tarefa (não menos difícil) é como criar algum tipo de API que resida no ECS e que você possa usá-lo com a mesma facilidade que o MonoBehaviour. I.e. não há resposta para a pergunta "quando exatamente".

- O ECS e o restante dos itens estão focados em pegar um GameObject básico e criar 150 mil de seus clones e gerenciá-los. Mas e se eu tiver poucos objetos, mas eles tiverem entidades diferentes?

- Você pode, em princípio, não fazer nada, esta tecnologia não obriga a usá-la. Se você pode obter um aumento de desempenho usando essas tecnologias, deve usá-las. Se isso não for relevante para você, você continuará usando o Unity como está. Portanto, não entre em pânico.

- Temos um cliente no Unity, um servidor no .NET, tentamos um servidor no Unity, nada resulta disso. Mas, ao mesmo tempo, também quero usar as tecnologias que estão no Unity no servidor.

- Estamos trabalhando nisso e entendemos que agora não podemos fornecer uma solução eficaz para servidores. Nós compramos a empresa Multiplay há algum tempo para criar hospedagem de alta qualidade para jogos Unity. Trabalhamos em rede separadamente e estamos comprometidos em otimizar o mecanismo para que mais coisas possam ser implementadas. Assim, quando tudo se reunir, teremos uma excelente solução multiplayer.

Mais conversas com o Pixonic DevGAMM Talks


Source: https://habr.com/ru/post/pt427359/


All Articles