Por que eu deveria sempre considerar criar e usar pools de objetos em vez de instanciar o novo objeto em tempo real?

25

Eu li sobre esse padrão várias vezes (de uma perspectiva de melhores práticas):

Alocação de memória : em vez de instanciar o novo objeto rapidamente, sempre considere criar e usar conjuntos de objetos. Isso ajudará a menos fragmentação da memória e fará com que o coletor de lixo funcione menos.

No entanto, não sei o que realmente significa. Como posso implementá-lo?

Por exemplo, eu posso instanciar um GameObjectusando o Instantiatemétodo da Unity?

Instantiate(prefab, new Vector3(2.0F, 0, 0), Quaternion.identity);

Esse uso é desencorajado? O que mais isso pode significar?

Muhammad Faizan Khan
fonte
Primeiro link no Google;) unity3d.com/fr/learn/tutorials/topics/scripting/object-Widget
Hellium 12/17
Graças hellium Eu não assisti o vídeo deu (muito grande), mas o texto realmente ajudar-me a compreender "O ato de instanciar e destruindo são ineficientes e podem retardar seus projetos down"
Muhammad Faizan Khan
11
Observe que, embora esse conselho seja comum, não é um requisito absoluto para todos os jogos. Especialmente se você estiver criando um jogo para área de trabalho pequeno / curto, envio de jam ou protótipo, não precisará se esforçar para implementar o pool. Nos meus testes de imersão, a Unity aguenta até a desova e a destruição maciças melhor do que acreditamos. ;) Mas considere o pool se você estiver fazendo um jogo longo em que não deseja que o lixo se acumule e cause gagueira quando for coletado posteriormente, ou se estiver direcionando plataformas móveis onde qualquer impacto no desempenho é sentido com mais intensidade.
DMGregory
Obrigado @DMGregory Você está certo. sua entrada é sempre valiosa. Não devemos nos preocupar com o pool de objetos em jogos pequenos, pois isso exigirá trabalho extra na codificação.
Muhammad Faizan Khan
11
Esse é um padrão muito comum, mas certifique-se de temperá-lo com a regra: "Primeiro perfil, depois otimize". É fácil otimizar coisas que não importam.
Cort Ammon - Restabelece Monica

Respostas:

41

Se você planeja instanciar muitas instâncias da mesma pré-fabricada, definitivamente deve pensar em usar o pool de objetos. Chamar a função Instanciar do Unity é um dos métodos mais exigentes que você pode fazer.

O pool de objetos é quando você instancia as prefabs antes de serem usadas. Eles são desativados imediatamente após a instanciação e reativados somente quando são necessários. Enquanto isso aumenta o uso de memória, evita a sobrecarga da CPU de instanciar durante o jogo.

Por exemplo, atualmente estou trabalhando em um jogo de balas que exige que centenas de balas sejam geradas em tempo de execução. Inicialmente, tentei fazer o jogo sem o pool de objetos, mas isso acabou sendo um desastre (menos de 2 qps). Agora, acumulo 500 marcadores antes do jogo começar e o jogo corre surpreendentemente rápido (200 fps).

Há situações em que o pool de objetos não pode ser usado. Por exemplo, se você tem um jogo em que a entrada do jogador determina qual pré-fabricada é gerada, talvez você não tenha outra opção a não ser usar a chamada Instantiate normal. O pool de objetos só é possível quando você sabe com antecedência quais objetos serão necessários.

O tutorial do YouTube de Sebastian Lague é um ótimo recurso para aprender sobre pool de objetos: https://youtu.be/LhqP3EghQ-Q

Kevin H.
fonte
"O ato de instanciar e destruir é ineficiente e pode atrasar seus projetos". Esta é a razão? Então, isso significa que temos de código um pouco mais (como Deactive ativar ou posição conjunto de bala novamente para que possamos disparar novamente)
Muhammad Faizan Khan
12
Vale a pena mencionar a alocação e a coleta de lixo como principais contribuintes para o custo da instanciação e destruição repetidas. Gere lixo suficiente e, eventualmente, o jogo inteiro terá que esperar o coletor de lixo varrer tudo. ;)
DMGregory
3
@corsiKa que seria uma otimização da era dos anos 80. O Unity pode simplesmente desativar os prefabs em questão, fazendo com que seus sistemas o ignorem.
congusbongus
2
"Por exemplo, se você tem um jogo em que a entrada do jogador determina qual pré-fabricada é gerada, talvez você não tenha outra escolha a não ser usar a chamada instantânea normal". - Na verdade não. Você poderia facilmente ter vários pools de objetos para diferentes prefabs alocados para os tamanhos desejados na inicialização (ou carregamento da cena). Ou, se alguém quiser fazer isso, um pool de objetos que armazena vários tipos de prefab também pode funcionar.
Ethan Bierlein
11
@DMGregory Em um ambiente típico de GC, a desalocação é a maior parte do custo; em um ambiente típico que não seja de GC, a alocação é a maior parte do custo. O pool de objetos funciona muito bem para ambos, na verdade eles são apenas dois lados da mesma moeda na maior parte. No caso extremo, jogos antigos costumavam ser escritos com todos os objetos "alocados" desde o início - pouca ou nenhuma memória / desalocação enquanto o jogo estava em execução. Você realmente não usou nada que não fosse "agrupado" de alguma forma. Como o Unity usa muitos "metadados" em tempo real, o pool pode ajudar bastante - embora também possa ser mais difícil de implementar.
Luaan 13/09/17