
Melhoria do desempenho de física para jogabilidade suave
Este é o quinto em uma série de artigos que revela dicas de otimização para seus projetos do Unity. Use-os como um guia para execução em taxas de quadros mais altas com menos recursos. Depois de testar essas práticas recomendadas, verifique as outras páginas da série:
- Configurando seu projeto do Unity para um desempenho mais forte
- Otimização de desempenho para gráficos de alta qualidade
- Gerenciando o uso da GPU para PC e jogos de console
- Arquitetura de código e programação avançada
A física pode criar jogabilidade complexa, mas isso acompanha um custo de desempenho. Depois de conhecer esses custos, você pode ajustar a simulação para gerenciá-la de maneira adequada. Use essas dicas para ficar dentro da taxa de quadros de destino e criar reprodução suave com o Physics integrado do Unity (NVIDIA PhysX).
Veja os nossos guias de otimização mais recentes para desenvolvedores e artistas em Unity 6:
Verifique seus colliders
As malhas usadas na física passam por um processo chamado cozinha. Isso prepara a malha para que possa trabalhar com consultas de física, como raycasts, contatos e assim por diante.
Um MeshCollider tem várias CookingOptions para ajudar você a validar a malha para a física. Se você tem certeza de que sua malha não precisa dessas verificações, desative-as para acelerar seu tempo de cozinha.
Em CookingOptions para cada MeshCollider, basta desmarcar EnableMeshCleaning, WeldColocatedVertices e CookForFasterSimulation. Essas opções são valiosas para malhas geradas de maneira procedural no tempo de execução, mas podem ser desativadas se suas malhas já tiverem os triângulos adequados.
Além disso, se você estiver segmentando PC, mantenha o Use Fast Midphase habilitado. Isso muda para um algoritmo mais rápido do PhysX 4.1 durante a fase intermediária da simulação (que ajuda a limitar um pequeno conjunto de triângulos potencialmente intersectores para consultas de física).
Saiba mais na documentaçãoCookingOptions.

Use Physics.BakeMesh
Se você estiver gerando malhas de maneira procedural durante a jogabilidade, poderá criar um Mesh Collider no tempo de execução. No entanto, adicionar um componente MeshCollider diretamente à malha prepara/bake a física na thread principal. Isso pode consumir tempo significativo da CPU.
Use o Physics.BakeMesh para preparar uma malha para uso com um MeshCollider e salvar os dados com baking com a malha em si. Um novo MeshCollider referenciando essa malha reutilizará esses dados pré-bake (em vez de fazer baking da malha novamente). Isso pode ajudar a reduzir o tempo de carregamento de cena ou instanciação posteriormente.
Para otimizar o desempenho, você pode descarregar a cozinha de malha em outra thread com o sistema de trabalho C#.
Consulte este exemplo para obter detalhes sobre como fazer baking de malhas em várias threads.

Ajuste suas configurações
Nas configurações do jogador, selecione Prebake Collision Meshes sempre que possível. Também recomendamos revisar a configuração do Collision Matrix para garantir que os objetos da mecânica do jogo e do jogador estejam nas camadas corretas.
Remover callbacks de gatilhos para camadas desnecessárias pode ser uma grande vantagem, então tente simplificar sua Layer Collision Matrix. Você pode editar suas configurações de física em Configurações de projeto > Física.
Saiba mais na documentação Collision Matrix.

Modifique a frequência da simulação
Engines de física funcionam em uma etapa do tempo fixa. Para ver a taxa fixa de execução do seu projeto, acesse Edit > Project Settings > Time.
O campo Fixed Timestep define a hora delta usada por cada etapa de física. Por exemplo, o valor padrão de 0,02 segundos (20 ms) é equivalente a 50 FPS, ou 50 Hz.
Como cada quadro em Unity leva uma quantidade variável de tempo, ele não é perfeitamente sincronizado com a simulação de física. A engine conta até a próxima etapa do tempo de física. Se um quadro for executado um pouco mais lento ou mais rápido, o Unity usará o tempo gasto para saber quando executar a simulação de física na etapa certa.
No caso de uma estrutura demorar muito para se preparar, isso pode causar problemas de desempenho. Por exemplo, se o seu jogo tiver um pico (por exemplo, instanciando muitos GameObjects ou carregando um arquivo do disco), a execução do quadro pode levar 40 ms ou mais. Com a Fixed Timestep de 20 ms padrão, isso faria com que duas simulações de física fossem executadas no quadro seguinte para “atender” a etapa temporal variável.
Simulações de física extras, por sua vez, adicionam mais tempo para processar o quadro. Em plataformas de baixo nível, isso pode gerar uma espiral de desempenho descendente.
Um quadro subsequente que leva mais tempo para se preparar também aumenta o atraso de simulações de física. Isso leva a quadros ainda mais lentos e ainda mais simulações para serem executadas por quadro. O resultado é desempenho cada vez pior.
Eventualmente, o tempo entre atualizações de física poderia exceder o Timestep máximo permitido. Depois desse corte, a Unity começa a lançar atualizações de física, e o jogo bate.
Para evitar problemas de desempenho com física:
- Reduza a frequência da simulação. Para plataformas mais básicas, aumente a Fixed Timestep para um pouco mais do que a taxa de quadros de destino. Por exemplo, use 0,035 segundos para 30 segundos em dispositivos móveis. Isso pode ajudar a impedir essa espiral de desempenho descendente.
- Reduza o Timestep máximo permitido. O uso de um valor menor (como 0,1 s) sacrifica a precisão da simulação de física, mas também limita a quantidade de atualizações de física que podem ocorrer em um quadro. Faça testes com valores para encontrar algo que funcione de acordo com os requisitos do seu projeto.
Simule a etapa de física manualmente, se necessário, selecionando o SimulationMode durante a fase de atualização do quadro. Isso permite que você controle quando executar a etapa de física. Passar Time.deltaTime para Physics.Simule para manter a física sincronizada com o tempo de simulação. Essa abordagem pode causar instabilidades na simulação de física em cenas com física complexa ou tempos de quadros altamente variáveis, então use com cautela.
Saiba mais na documentação Physics.Simule.

Use Box Pruning para cenas grandes
A engine Unity Physics funciona em duas etapas:
- A fase larga, que coleta possíveis colisões usando um algoritmo de pesca e prenda
- A fase estreita, onde a engine computa as colisões
A configuração padrão de fase ampla de Pesca e Prune BroadPhase (Editar > Configurações do projeto > Física > Tipo de fase ampla) pode gerar falsos positivos para mundos que são geralmente planos e têm muitos colliders.Se sua cena é grande e principalmente plana, evite esse problema e mude para Pesca automática ou Pesca multiboxes de fase ampla. Essas opções dividem o mundo em uma grade, em que cada célula da grade realiza varredura e prune.
O Multibox Pruning Broadphase permite que você especifique os limites do mundo e o número de células da grade manualmente, enquanto o Automatic Box Pruning calcula isso para você.
Veja a lista completa de propriedades de física aqui.

Modifique as iterações do solucionador
Se você quiser simular um corpo físico específico de forma mais precisa, aumente suas RigidBody.solverIterations.
Isso substitui o Physics.defaultSolverIterations, que também pode ser encontrado em Edit > Project Settings > Physics > Default Solver Iterations.
Para otimizar suas simulações de física, defina um valor relativamente baixo na configuração padrãoSolveIterations do projeto. Depois, aplique valores mais altos de Rigidbody.solverIterations personalizados para as instâncias individuais que precisam de mais detalhes.
Obtenha mais informações sobre Rigidbody.solverIterations.

Desative a sincronização automática de transformação
Por padrão, o Unity não sincroniza automaticamente as alterações no Transforms com a engine de física. Em vez disso, ele espera até a próxima atualização de física ou até você chamar manualmente Physics.SyncTransforms. Quando ativado, qualquer RigidBody ou Collider nesse Transform ou seus filhos são sincronizados automaticamente com a engine de física.
Quando sincronizar manualmente
Quando o autoSyncTransforms está desativado, o Unity sincroniza as transformações somente antes da etapa de simulação de física em FixedUpdate ou quando solicitado explicitamente por meio do Physics.Simulate. Talvez seja necessário realizar sincronizações adicionais se você usar APIs lidas diretamente da engine de física entre as alterações de Transform e a atualização de física. Exemplos incluem acessar Rigidbody.position ou executar o Physics.Raycast.
Melhor prática de desempenho
Embora o autoSyncTransforms garanta consultas de física atualizadas, ele incorre em um custo de desempenho. Cada chamada de API relacionada à física força uma sincronização, o que pode degradar o desempenho, especialmente com várias consultas sucessivas. Siga estas práticas recomendadas:
- Desativar autoSyncTransforms, a menos que necessário: Habilite-a somente se a sincronização precisa e contínua for crucial para a mecânica do seu jogo.
- Use a sincronização manual: Para um melhor desempenho, sincronize manualmente o Transforms com o Physics.SyncTransforms() antes de chamadas que exigem os dados mais recentes do Transform. Essa abordagem é mais eficiente do que habilitar o autoSyncTransforms globalmente.
Saiba mais sobre o Physics.SyncTransforms.

Reutilizar Collision Callbacks
As matrizes de contatos geralmente são significativamente mais rápidas e, portanto, a recomendação geral é usá-las em vez de reutilizar callbacks de colisão. No entanto, considere o seguinte caso de uso específico.
Os callbacks MonoBehaviour.OnCollisionEnter, MonoBehaviour.OnCollisionStay e MonoBehaviour.OnCollisionExit todos assumem uma instância de colisão como um parâmetro. Esta instância de colisão é alocada no pilha gerenciada e deve ser coletada pelo Garbage.
Para reduzir a quantidade de lixo gerado, ative Physics.reuseCollisionCallbacks (também encontrado em Configurações de projetos > Physics > Reuse Collision Callbacks). Com essa ativação, o Unity atribui apenas uma única instância de par de colisões a cada callback. Isso reduz os resíduos do Garbage Collector e melhora o desempenho.
A recomendação geral é habilitar Reuse Collision Callbacks para obter benefícios de desempenho. Você deve desativar esse recurso apenas para projetos legados nos quais o código depende de instâncias de classe de Collision individuais, tornando impraticável armazenar campos individuais.
Saiba mais sobre o Physics.reuseCollisionCallbacks.

Mover Colliders estáticos
Colliders estáticos são GameObjects com um componente Collider, mas sem um RigidBody.
Observe que você pode mover um collider estático, ao contrário do termo “estático”. Para isso, basta modificar a posição do corpo de física. acumule as alterações posicionais e sincronize antes da atualização de física. Você não precisa adicionar um componente RigidBody ao collider estático apenas para movê-lo.
No entanto, se você quiser que o collider estático interaja com outros corpos físicos de maneira mais complexa, dê um RigidBody cinemático. Use Rigidbody.position e Rigidbody.rotation para movê-la em vez de acessar o componente Transform. Isso garante um comportamento mais previsível da engine de física.
Observação: Se um Static Collider 2D precisa ser movido ou reconfigurado no tempo de execução, adicione um componente Rigidbody 2D e defina-o para o Tipo de Corpo Estático, pois é mais rápido simular o Collider 2D quando tiver seu próprio Rigidbody 2D. Se um grupo de Collider 2Ds precisar ser movido ou reconfigurado no tempo de execução, será mais rápido fazer com que todos sejam filhos do único Rigidbody 2D pai oculto do que mover cada GameObject individualmente.
Obtenha mais informações sobre RigidBods.
Use consultas não alocadas
Para detectar e coletar colliders em projetos 3D dentro de uma certa distância e em uma certa direção, use raycasts e outras consultas de física, como BoxCast. Observe que
As consultas de física que retornam vários colliders como uma matriz, como OverlapSphere ou OverlapBox, precisam alocar esses objetos na pilha gerenciada. Isso significa que o Garbage Collector eventualmente precisará coletar os objetos alocados, o que pode diminuir o desempenho se acontecer no momento errado.
Para reduzir essa sobrecarga, use as versões NonAlloc dessas consultas. Por exemplo, se você estiver usando OverlapSphere para coletar todos os colliders potenciais em um ponto, use OverlapSphereNonAlloc.
Isso permite que você passe em uma matriz de colliders (o resultado parâmetro) para atuar como um buffer. O método NonAlloc funciona sem gerar lixo. Caso contrário, ele funciona igual ao método de alocação correspondente.
Observe que é necessário definir um buffer de resultados de tamanho suficiente ao usar um método NonAlloc. O buffer não cresce se estiver sem espaço.
Física do 2D
Observe que o conselho acima não se aplica a consultas de física 2D, pois no sistema de física 2D do Unity, os métodos não têm um sufixo "NonAlloc". Em vez disso, todos os métodos de física 2D, incluindo aqueles que retornam vários resultados, fornecem sobrecargas que aceitam matrizes ou listas. Por exemplo, enquanto o sistema de física 3D tem métodos como RaycastNonAlloc, o equivalente 2D simplesmente usa uma versão sobrecarregada do Raycast que pode levar uma matriz ou lista como um parâmetro, como:
var results = new List();
int hitCount = Physics2D.Raycast(origin, direção, contatoFilter, resultados);
Usando sobrecargas, você pode realizar consultas não alocadas no sistema de física 2D sem a necessidade de métodos NonAlloc especializados.
Saiba mais na documentação do método NonAlloc.
Perguntas em lote para raycasting
Você pode executar consultas de raycast com o Physics.Raycast. No entanto, se você tiver um grande número de operações de raycast (por exemplo, calcular a linha de visão para 10.000 agentes), isso pode levar uma quantidade significativa de tempo da CPU.
Use o RaycastCommand para agrupar a consulta usando o sistema de trabalhos em C#. Isso descarrega o trabalho da thread principal para que as raycasts possam ocorrer de maneira assíncrona e em paralelo.
Veja um exemplo na documentaçãoRaycastCommands.
Visualize com o Physics Debugger
Use a janela Physics Debug (Janela > Análise > Physics Debugger) para ajudar a solucionar problemas de colliders ou discrepâncias. Isso mostra um indicador codificado por cores dos GameObjects que podem colidir entre si.
Para obter mais informações, consulte a documentação do Physics Debugger.


Encontre mais práticas recomendadas e dicas do hub de práticas recomendadas da Unity. Escolha entre mais de 30 guias, criados por especialistas do setor, engenheiros e artistas técnicos da Unity, que ajudarão você a desenvolver com eficiência com os conjuntos de ferramentas e sistemas da Unity.