No mecanismo Source (e é antecessor, goldsrc, quake's), os objetos do jogo são divididos em dois tipos, mundo e entidades. O mundo é a geometria do mapa e as entidades são jogadores, partículas, sons, partituras, etc. (para o Source Engine).
Toda entidade possui uma função de pensamento , que faz toda a lógica dessa entidade.
Portanto, se tudo o que precisa ser processado vier de uma classe base com a função think, o mecanismo de jogo poderá armazenar tudo em uma lista e, em todos os quadros, percorrê-lo e chamar essa função.
Em um primeiro olhar, essa ideia é razoável, mas pode levar muitos recursos, se o jogo tiver muitas entidades.
Então, como um mecanismo como o Source cuida (processo, atualização, desenho etc.) dos objetos do jogo?
<some commercial engine>
isso acontece?Respostas:
Bem, não há praticamente nenhuma outra maneira de fazer isso - você terá que percorrer e chamar
think()
todas as entidades pelo menos uma vez a cada poucos quadros.Você pode colocar entidades em seu próprio encadeamento, mas terá todo o pesadelo de sincronização de estado, o que definitivamente não vale a pena.
É por isso que o mecanismo de origem impõe um limite rígido ao número de entidades que podem existir ao mesmo tempo : 4096 entidades, das quais apenas metade (2048) pode ser conectada em rede. Passe por um desses limites e o jogo travará.
É também por isso que, ao criar um mapa, eles recomendam que você não use mais de 800 entidades.
fonte
Essas etapas que você menciona provavelmente são executadas em mecanismos separados. É que os mecanismos de jogo simples geralmente os têm de uma só vez. Sua sequência
torna-se
O Physics Engine cuida de posições e tamanhos.
O Game Logic Engine cuida da interpretação do que o Physics Engine mudou (ele pode obstruir alguns pontos de referência ...), quais objetivos os personagens têm e qual comportamento eles devem estar executando , ele executa scripts agendados (este pensamento função de ).
O Drawing Engine desenha quais objetos são visíveis e ele sabe quais objetos são visíveis porque os mecanismos do Quake meio que trapaceiam aqui (consulte a seção Draw).
Meu conselho para você é estudar melhor como as simulações são feitas, em vez dos mecanismos de jogo. Existe uma enorme cultura pop relacionada ao desenvolvimento de jogos e os mecanismos de jogos são feitos em linguagens imperativas (por causa da tradição e velocidade); então foi mais esclarecedor para mim obter bons livros didáticos (em vez de teoria) e ENTÃO olhar para os motores (prática) do que olhar para os motores e os quebra-cabeças por horas como eles fizeram isso.
Física
A noção completa de iterar todas as entidades e {pensar, desenhar} provavelmente levará a problemas. Haverá conflitos e assim por diante. Acredito que a Valve tenha Havok e acho que Havok cuida da física correta o suficiente.
Pensar
A função Think é executada quando um tempo em um jogo é igual ao tempo no nextthink . Funciona dessa maneira no mecanismo Quake, e o mecanismo Quake é a base dos mecanismos Half Life. NÃO é executado todas as vezes.
Internamente, deve ser uma iteração simples através de uma lista de entidades e verificar se já passou o tempo para chamar a função think. A complexidade do tempo será O (N), onde N é o número de entidades.
Se houver um número muito grande de entidades, você deve medir quanto melhorará os fps. Observe que, devido à lei de Amdahl , é uma aceleração potencialmente invisível. Quero dizer, você apenas percorre todos os itens e diminui e verifica um número.
Eu o aceleraria classificando entidades pelo nextthink (crie uma lista de ponteiros para entidades e classifique-a sempre; não uma matriz de entidades, porque as entidades podem alterar seu nextthink a qualquer momento, portanto, reorganizá-las na matriz leva O (N) em vez de O ( 1) na lista).
Você também deve consultar o planejador O (1) no Linux .
Desenhar
Motor desenha o que é aproximadamente visível da área em que a câmera está. O nível do jogo é particionado em uma árvore e uma área é a folha dessa árvore. Não vou incomodá-lo com detalhes sobre isso ... Então, se uma entidade é visível, ela é colocada em um conjunto de entidades visíveis e elas são desenhadas.
Eles armazenam quais áreas são áreas potencialmente visíveis. É chamado de "conjunto potencialmente visível", PVS, para abreviar. Há visualização do PVS , a cápsula verde é o jogador e ao seu redor é renderizado o que o seu PVS contém.
fonte
Na verdade, colocar tudo em uma grande lista geralmente é menos do que desejável; se você agrupar as entidades em listas com base, por exemplo, no tipo delas, poderá distribuir melhor o processamento por vários encadeamentos. Por exemplo, se você souber que todas as entidades do tipo Foo nunca interagem com outras entidades durante a fase de simulação, é possível descarregá-las completamente. Se eles estivessem espalhados por toda parte, em uma lista grande e singular, isso seria muito mais difícil de fazer.
Você nem precisa estar derivando tudo de uma classe base comum nesse ponto; A origem é exagerada com o abuso de herança pelo que poderia ser implementado como dados a esse respeito.
Obviamente, você sempre terá um limite superior no número de entidades que pode processar por quadro, mesmo se começar a descarregar o trabalho para outros núcleos. Não há como contornar isso, você só precisa ter uma idéia do que esse limite é na sua implementação e tomar medidas para aliviá-lo (seleção adequada das fases de processamento de objetos que não precisam deles, evitando excesso de granularidade nos objetos, etc. cetera).
fonte
O que você deve levar em consideração e seguir esta linha de pensamento das respostas anteriores é que seu desempenho também será quando e como você chama essas funções de pensamento.
Olhando para o link que você postou no mecanismo de origem, você também pode ler que pode configurar tempos de reflexão e diferentes contextos de reflexão para cada uma de suas entidades, além do óbvio limite rígido que alguém já apontou, essa será a chave para obter maior desempenho com um número maior de entidades, seja criando atualizações escalonadas que espalham o processamento com fome de desempenho por vários quadros de execução ou eliminando o processamento desnecessário, dependendo do contexto atual (ou seja, entidades que estão muito distantes ou além da percepção do jogador não precisam o mesmo nível de "pensar em detalhes" dos personagens próximos de um jogador simplesmente não vê um personagem a 3 km de distância, mordendo o nariz).
E há outros níveis mais específicos de otimização, dependendo da sua lógica e situação do jogo.
fonte