Esta página descreve problemas comuns de desempenho e as melhores práticas para mitigá-los.
Computação de scripts
Operações caras no código Luau demoram mais para serem processadas e, portanto, podem afetar a taxa de quadros.A menos que esteja sendo executado em paralelo, o código Luau é executado em sincronia e bloqueia o subprocesso principal até encontrar uma função que gera o subprocesso.
Problemas comunes
Operações intensivas em estruturas de tabela - Operações complexas como serialização, deserialização e clonamento profundo incorrem em alto custo de desempenho, especialmente em grandes estruturas de tabela.Isso é particularmente verdadeiro se essas operações forem recorrentes ou envolverem a iteração sobre estruturas de dados muito grandes.
Eventos de alta frequência - Vincular operações caras a eventos baseados em quadros de RunService sem limitar a frequência significa que essas operações são repetidas a cada quadro, o que muitas vezes resulta em um aumento desnecessário no tempo de cálculoEsses eventos incluem:
Mitigação
- Invocar código em RunService eventos de forma esporádica, limitando o uso a casos em que a invocação de alta frequência é essencial (por exemplo, atualizar a câmera).Você pode executar a maior parte do código restante em outros eventos ou com menos frequência em um loop.
- Quebre grandes ou caras tarefas usando task.wait() para distribuir o trabalho em vários quadros.
- Identifique e otimize operações desnecessariamente caras e use multithreading para tarefas computacionalmente caras que não precisam acessar o modelo de dados.
- Determinados scripts do lado do servidor podem se beneficiar de geração de código nativo, uma bandeira simples que compila um script para código de máquina em vez de bytecode.
Escopos do MicroProfiler
Âmbito | Computação associada |
RunService.PreRender | Código executando no evento PreRender |
ExecutarServiço.PreSimulação | Código executando no evento Stepped |
RunService.PostSimulação | Código executando no evento de Batimento Cardíaco |
RunService.Batimento de Coração | Código executando no evento de Batimento Cardíaco |
Para mais informações sobre a depuração de scripts usando o MicroProfiler, consulte a biblioteca debug, que inclui funções para marcar código específico e aumentar ainda mais a especificidade, como debug.profilebegin e debug.profileend.Muitos métodos da API do Roblox chamados por scripts também têm suas próprias tags de MicroProfiler associadas que podem fornecer sinal útil.
Uso da memória do script
Vazamentos de memória podem ocorrer quando você escreve scripts que consomem memória que o coletor de lixo não pode liberar corretamente quando não estiver mais em uso.Vazamentos são especificamente pervasivos no servidor, porque eles podem estar online continuamente por muitos dias, enquanto uma sessão de cliente é muito mais curta.
Os seguintes valores de memória no Console do Desenvolvedor podem indicar um problema que precisa de mais investigação:
- LuaHeap - Consumo alto ou crescente sugere uma fuga de memória.
- Contagem de Instâncias - Consistente crescimento de número de instâncias sugere que referências a algumas instâncias em seu código não estão sendo coletadas em garbage.
- PlaceScriptMemory - Fornece um script por quebra de script de uso de memória.
Problemas comunes
Deixar conexões conectadas - O motor nunca coleta lixo eventos conectados a uma instância e quaisquer valores referenciados dentro do retorno de chamada conectado.Portanto, conexões ativas de eventos e código dentro das instâncias conectadas, funções conectadas e valores referenciados estão fora do escopo do coletor de lixo de memória, mesmo após os eventos serem disparados.
Embora os eventos sejam desconectados quando a instância a que pertencem for destruída, um erro comum é assumir que isso se aplica a Player comuns.Depois que um usuário deixa uma experiência, o motor não destrói automaticamente o objeto e o modelo de personagem representativo Player do usuário e, portanto, as conexões ao objeto Player e às instâncias sob o modelo de personagem, como Player.CharacterAdded, ainda consomem memória se você não desconectá-los em seus scripts.Isso pode resultar em vazamentos de memória muito significativos ao longo do tempo no servidor, à medida que centenas de usuários entram e saem da experiência.
Tabelas - Inserir objetos em tabelas, mas não removê-los quando eles não forem mais necessários causa consumo desnecessário de memória, especialmente para tabelas que rastreiam dados do usuário quando se juntam.Por exemplo, o seguinte código de exemplo cria uma tabela que adiciona informações do usuário sempre que um usuário se junta:
Exemplolocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- algumas informaçõesend)Se você não remover essas entradas quando elas não forem mais necessárias, a tabela continua a crescer em tamanho e consome mais memória à medida que mais usuários entram na sessão.Qualquer código que iterar sobre essa tabela também se torna mais caro em termos de cálculo à medida que a tabela cresce em volume.
Mitigação
Para limpar todos os valores usados para evitar vazamentos de memória:
Desconecte todas as conexões - Percorra sua base de código para garantir que cada conexão seja limpa através de um dos seguintes caminhos:
- Desconectando manualmente usando a função Disconnect() .
- Destruindo a instância a qual o evento pertence com a função Destroy().
- Destruindo o objeto de script ao qual as conexões remontam.
Remova objetos e personagens do jogador após sair - Implemente código para garantir que nenhuma conexão persista depois que um usuário sair, como no seguinte exemplo:
ExemploPlayers.PlayerAdded:Connect(function(player)player.CharacterRemoving:Connect(function(character)task.defer(character.Destroy, character)end)end)Players.PlayerRemoving:Connect(function(player)task.defer(player.Destroy, player)end)
Computação de Física
A simulação de física excessiva pode ser uma causa importante do aumento do tempo de cálculo por quadro no servidor e no cliente.
Problemas comunes
Frequência excessiva de passos de física - Por padrão, o comportamento de passos está em modo adaptativo, onde os passos de física estão em 60 Hz, 120 Hz ou 240 Hz, dependendo da complexidade do mecanismo de física.
Um modo fixo com precisão aprimorada da física também está disponível, que força todas as montagens de física a passar em 240 Hz (quatro vezes por quadro).Isso resulta em significativamente mais cálculo em cada quadro.
Número excessivo de complexidade de objetos simulados - Quanto mais montagens 3D forem simuladas, mais tempo as operações de física levarão a cada quadro.Muitas vezes, as experiências terão objetos sendo simulados que não precisam ser ou terão mecanismos que têm mais restrições e articulações do que precisa.
Detecção de colisão excessivamente precisa - As peças de malha têm uma propriedade CollisionFidelity para detectar colisão que oferece uma variedade de modos com diferentes níveis de impacto de desempenho.O modo de detecção de colisão preciso para peças de malha tem o custo de desempenho mais caro e leva mais tempo para o motor computar.
Mitigação
Ancorar peças que não requerem simulação - Ancorar todas as peças que não precisam ser movidas pela física, como para NPCs estáticos.
Use passos de física adaptativa - Passos adaptativos ajustam dinamicamente a taxa de cálculos de física para mecanismos de física, permitindo que atualizações de física sejam feitas com menos frequência em alguns casos.
Reduza a complexidade do mecanismo * Na medida do possível, minimize o número de restrições ou junções de física em uma montagem.
- Reduza a quantidade de colisão entre si dentro de um mecanismo, como aplicando limites ou restrições de colisão a membros de ragdoll para impedi-los de colidir uns com os outros.
Reduza o uso de precisa fidelidade de colisão para malhas * Para objetos pequenos ou não interativos onde os usuários raramente perceberiam a diferença, use a fidelidade da caixa.
Para objetos de tamanho pequeno a médio, use a fidelidade da caixa ou do casco, dependendo da forma.
Para objetos grandes e muito complexos, construa colisões personalizadas usando partes invisíveis sempre que possível.
Para objetos que não requerem colisões, desative colisões e use a fidelidade da caixa ou do casco, pois a geometria de colisão ainda está armazenada na memória.
Você pode renderizar geometria de colisão para fins de depuração no Studio ativando fidelidade de colisão a partir do widget Opções de Visualização no canto superior direito do visualizador 3D.
Alternativamente, você pode aplicar o CollisionFidelity = Precise ao Explorador, que mostra um número de todas as peças de malha com a precisa fidelidade e permite que você as selecione facilmente.
Para uma caminhada detalhada sobre como escolher uma opção de fidelidade de colisão que equilibre seus requisitos de precisão e desempenho, veja Definir Parâmetros de Física e Rendering.
Escopos do MicroProfiler
Âmbito | Computação associada |
físicaStepped | Computação de física geral |
passo mundial | Passos de física discreta realizados a cada quadro |
Uso de memória física
O movimento físico e a detecção de colisão consomem memória.As peças de malha têm uma propriedade CollisionFidelity que determina a abordagem que é usada para avaliar os limites de colisão da rede.
Problema comum
Os modos padrão e precisos de detecção de colisão consomem significativamente mais memória do que os dois outros modos com formas de colisão de fidelidade mais baixa.
Se você ver altos níveis de consumo de memória sob Peças de Física , talvez precise explorar reduzir a fidelidade de colisão de objetos em sua experiência.
Como amenizar
Para reduzir a memória usada para a fidelidade de colisão:
- Para peças que não precisam de colisões, desative suas colisões definindo BasePart.CanCollide , BasePart.CanTouch e BasePart.CanQuery para false .
- Reduza a fidelidade das colisões usando a configuração CollisionFidelity.Box tem o menor excesso de memória e Default e Precise são geralmente mais caros.
- É geralmente seguro definir a fidelidade de colisão de qualquer peça ancorada pequena para Box .
- Para malhas grandes muito complexas, você pode querer criar sua própria malha de colisão a partir de objetos menores com fidelidade de colisão em caixa.
Humanóides
Humanoid é uma classe que fornece uma ampla gama de funcionalidades para personagens jogadores e não jogadores (NPCs).Embora seja poderoso, um Humanoid vem com um custo de cálculo significativo.
Problemas comunes
- Deixar todos os HumanoidStateTypes ativados em NPCs - Existe um custo de desempenho ao deixar determinados HumanoidStateTypes ativados.Desabilite qualquer um que não seja necessário para seus NPCs.Por exemplo, a menos que seu NPC vá escalar escadas, é seguro desativar o estado Climbing .
- Instanciando, modificando e respawnando modelos com Humanoids frequentemente * Isso pode ser intenso para o motor processar, especialmente se esses modelos usam roupas em camadas .Isso também pode ser particularmente problemático em experiências em que os avatares reaparecem frequentemente.
- No MicroProfiler , etiquetas de atualização longas updateInvalidatedFastClusters (com mais de 4 ms) são frequentemente um sinal de que a instalação/modificação do avatar está gerando invalidificações excessivas.
- Usando Humanoides em casos em que eles não são necessários - NPCs estáticos que não se movem geralmente não têm necessidade da classe Humanoid.
- Jogar animações em um grande número de NPCs do servidor - As animações de NPCs que são executadas no servidor precisam ser simuladas no servidor e replicadas para o clienteIsso pode ser desnecessário excesso.
Mitigação
- Jogue animações de NPC no cliente - Em experiências com um grande número de NPCs, considere criar o Animator no cliente e executar as animações localmente.Isso reduz a carga no servidor e a necessidade de replicação desnecessária.Também torna possíveis otimizações adicionais (como apenas reproduzir animações para NPCs que estão perto do personagem).
- Use alternativas amigáveis ao desempenho para Humanoids - Os modelos de NPC não precisam necessariamente conter um objeto humanoide.
- Para NPCs estáticos, use um simples AnimationController, pois eles não precisam se mover, mas apenas precisam jogar animações.
- Para mover NPCs, considere implementar seu próprio controlador de movimento e usar um AnimationController para animações, dependendo da complexidade de seus NPCs.
- Desabilite estados humanóides não utilizados - Use Humanoid:SetStateEnabled() para habilitar apenas os estados necessários para cada humanóide.
- Modelos NPC de piscina com respawn frequente - Em vez de destruir um NPC completamente, envie o NPC para uma piscina de NPCs inativos.Dessa forma, quando um novo NPC é necessário para reaparecer, você pode simplesmente reativar um dos NPCs da piscina.Esse processo é chamado de pooling, que minimiza a quantidade de vezes em que os personagens precisam ser instanciados.
- Gerar apenas NPCs quando os usuários estiverem próximos - Não gerar NPCs quando os usuários não estiverem ao alcance, e eliminá-los quando os usuários deixarem seu alcance.
- Evite fazer alterações na hierarquia de avatar depois que ela for instanciada - Determinadas modificações em uma hierarquia de avatar têm implicações de desempenho significativasAlgumas optimizações estão disponíveis:
- Para animações procedurais personalizadas, não atualize as propriedades JointInstance.C0 e JointInstance.C1. Em vez disso, atualize a propriedade Motor6D.Transform.
- Se você precisar anexar quaisquer objetos BasePart ao avatar, faça isso fora da hierarquia do avatar Model .
Escopos do MicroProfiler
Âmbito | Computação associada |
passoHumanoid | Controle e física de humanóide |
animação de passos | Animação humanoide e de animador |
atualizarClustersInvalidadosFast | Relacionado com a instalação ou modificação de um avatar |
Renderização
Uma porção significativa do tempo que o cliente gasta em cada quadro é na renderização da cena no quadro atual.O servidor não faz nenhum renderizamento, então esta seção é exclusiva para o cliente.
Executar chamadas
Um chamado de desenho é um conjunto de instruções do motor para a GPU para renderizar algo.Chamadas de desenho têm sobrecarga significativa.Em geral, quanto menos chamadas de desenho por quadro, menos tempo de computação é gasto para renderizar um quadro.
Você pode ver quantas chamadas de desenho estão ocorrendo atualmente com o item Estatísticas de renderização > Tempo no Studio.Você pode ver Estatísticas de renderização no cliente pressionando ShiftF2.
Quanto mais objetos precisam ser desenhados em sua cena em um determinado quadro, mais chamadas de desenho são feitas para a GPU.No entanto, o Motor do Roblox utiliza um processo chamado instancialização para colapsar malhas idênticas com as mesmas características de textura em uma única chamada de desenho.Especificamente, várias malhas com o mesmo MeshId são tratadas em uma única chamada de desenho quando:
- Os materiais são idênticos quando ambos SurfaceAppearance e MeshPart.TextureID não existem.
Outros problemas comunes
Densidade excessiva de objetos - Se um grande número de objetos estiver concentrado com uma alta densidade, então renderizar essa área da cena requer mais chamadas de desenho.Se você está encontrando quedas na taxa de quadros ao olhar para uma determinada parte do mapa, isso pode ser um bom sinal de que a densidade de objetos nessa área é muito alta.
Objetos como adesivos, texturas e partículas não se batcham bem e introduzem chamadas de desenho adicionais.Preste extra atenção a esses tipos de objetos em uma cena.Em especial, as alterações de propriedade para ParticleEmitters podem ter um impacto dramático no desempenho.
Oportunidades perdidas de instanciamento - Muitas vezes, uma cena incluirá a mesma malha duplicada várias vezes, mas cada cópia da malha tem IDs de recurso de malha ou textura diferentesIsso impede a instância e pode levar a chamadas de desenho desnecessárias.
Uma causa comum desse problema é quando toda uma cena é importada de uma só vez, em vez de importar recursos individuais para o Roblox e depois duplicá-los após a importação para montar a cena.
Complicação excessiva de objetos - Embora não seja tão importante quanto o número de chamadas de desenho, o número de triângulos em uma cena influencia o tempo que leva para renderizar uma imagem.Cenas com um número muito grande de malhas muito complexas são um problema comum, assim como cenas com o conjunto de propriedades MeshPart.RenderFidelity definido como Enum.RenderFidelity.Precise em muitas malhas.
Lançamento excessivo de sombras - Manejar sombras é um processo caro, e mapas que contêm um número e densidade elevados de objetos de luz que lançam sombras (ou um número e densidade elevados de peças pequenas influenciadas por sombras) provavelmente terão problemas de desempenho.
Alta sobrecarga de transparência - Colocar objetos com transparência parcial próximos uns dos outros força o motor a renderizar os pixels sobrepostos várias vezes, o que pode prejudicar o desempenho.Para mais informações sobre a identificação e correção deste problema, veja Excluir transparências em camadas.
Mitigação
- Instanciando malhas idênticas e reduzindo a quantidade de malhas únicas - Se você garantir que todas as malhas idênticas tenham os mesmos IDs de recurso subjacentes, o motor pode reconhecê-las e renderizá-las em uma única chamada de desenho.Certifique-se de fazer apenas o upload de cada malha em um mapa uma vez e depois duplicá-las no Studio para reutilização, ao invés de importar grandes mapas como um todo, o que pode causar que malhas idênticas tenham IDs de conteúdo separados e sejam reconhecidas como recursos únicos pelo motor.Pacotes são um mecanismo útil para reutilização de objetos.
- Seleção - A seleção descreve o processo de eliminação de chamadas de desenho para objetos que não entram no quadro final renderizado.Por padrão, o motor ignora chamadas de desenho para objetos fora do campo de visão da câmera (coleta de frustum), mas não ignora chamadas de desenho para objetos ocultos de vista por outros objetos (coleta de occlusão).Se sua cena tiver um grande número de chamadas de desenho, considere implementar sua própria exclusão adicional em tempo de execução dinamicamente para cada quadro, como aplicar as seguintes estratégias comuns:
- Para ambientes internos, implemente um sistema de sala ou portal que esconda objetos que não estão atualmente ocupados por nenhum usário.
- Reduzindo a fidelidade de renderização - Defina a fidelidade de renderização para Automática ou Desempenho .Isso permite que malhas retornem a alternativas menos complexas, o que pode reduzir o número de polígonos que precisam ser desenhados.
- Desabilitando lançamento de sombra em peças e objetos de luz apropriados - A complexidade das sombras em uma cena pode ser reduzida desabilitando seletivamente propriedades de lançamento de sombra em objetos de luz e peças.Isso pode ser feito no momento de edição ou dinamicamente em tempo de execução.Alguns exemplos são:
Use a propriedade BasePart.CastShadow para desativar o lançamento de sombras em peças pequenas onde as sombras provavelmente não serão visíveis.Isso pode ser particularmente eficaz quando aplicado apenas a partes que estão longe da câmera do usuário.
Desabilite sombras em objetos em movimento quando possível.
Desabilite Light.Shadows em instâncias leves onde o objeto não precisa lançar sombras.
Limite o alcance e o ângulo das instâncias de luz.
Use menos instâncias leves.
Escopos do MicroProfiler
Âmbito | Computação associada |
Prepare e Execute | Rendimento geral |
Executar/Cena/ computeLightingPerform | Atualizações de grade de luz e sombra |
LuzGridCPU | Atualizações da grade de luz de voxel |
Sistema ShadowMap | Mapa de sombras |
Executar/Cena/AtualizarVisualização | Preparação para renderização e atualizações de partes |
Executar/Cena/RenderizarVista | Renderização e pós-processamento |
Redes e replicação
Rede e replicação descrevem o processo pelo qual os dados são enviados entre o servidor e os clientes conectados.Informações são enviadas entre o cliente e o servidor a cada quadro, mas quantidades maiores de informações exigem mais tempo de processamento.
Problemas comunes
Tráfego remoto excessivo - Enviar uma grande quantidade de dados através de ou objetos ou invocá-los com muita frequência pode levar a uma grande quantidade de tempo de CPU gasto processando pacotes recebidos a cada quadro.Os erros comuns incluem:
- Replicando dados a cada quadro que não precisa ser replicado.
- Replicando dados na entrada do usuário sem nenhum mecanismo para limitá-lo.
- Enviando mais dados do que o necessário.Por exemplo, enviar todo o inventário do jogador quando eles comprarem um item, em vez de apenas detalhes do item comprado.
Criação ou remoção de árvores de instâncias complexas - Quando uma alteração é feita no modelo de dados no servidor, ela é replicada para os clientes conectados.Isso significa que criar e destruir grandes hierarquias de instâncias, como mapas, durante a execução pode ser muito intensivo em rede.
Um culpado comum aqui é os dados de animação complexos salvos pelos plugins do Editor de Animação em modelos.Se esses não forem removidos antes de o jogo ser publicado e o modelo animado for clonado regularmente, uma grande quantidade de dados será replicada desnecessariamente.
Serviço de transição do lado do servidor - Se TweenService for usado para transicionar um servidor de objetos do lado do servidor, a propriedade transicionada é replicada para cada cliente a cada quadro.Não só isso resulta no adolescente estar nervoso à medida que a latência dos clientes oscila, mas também causa muito tráfego de rede desnecessário.
Mitigação
Você pode empregar as seguintes táticas para reduzir a replicação desnecessária:
- Evite enviar grandes quantidades de dados de uma vez por meio de eventos remotos .Em vez disso, envie apenas os dados necessários com uma frequência menor.Por exemplo, para o estado de um personagem, replicá-lo quando ele muda, em vez de a cada quadro.
- Separe árvores de instâncias complexas como mapas e carregue-as em pedaços para distribuir o trabalho replicando-os em vários quadros.
- Limpe o metadado de animação , especialmente o diretório de animação de modelos, após a importação
- Limite a replicação desnecessária de instâncias , especialmente em casos em que o servidor não precisa ter conhecimento das instâncias que estão sendo criadas.Isso inclui:
- Efeitos visuais, como uma explosão ou um ataque de feitiço mágico.O servidor só precisa saber a localização para determinar o resultado, enquanto os clientes podem criar visualizações localmente.
- Modelos de visualização de itens em primeira pessoa.
- Objetos de transição no cliente em vez do servidor.
Escopos do MicroProfiler
Âmbito | Computação associada |
Pacotes de processamento | Processando pacotes de rede recebidos, como invocações de eventos e mudanças de propriedade |
Alocar largura de banda e executar remetentes | Eventos de saída relevantes nos servidores |
Uso de memória de recurso
O mecanismo de maior impacto disponível para os criadores para melhorar o uso de memória do cliente é habilitar Streaming de Instância.
streaming de instância
A transmissão de instâncias carrega seletivamente partes do modelo de dados que não são necessárias, o que pode levar a um tempo de carregamento consideravelmente reduzido e aumentar a capacidade do cliente de evitar quedas quando estiver sob pressão de memória
Se você estiver enfrentando problemas de memória e tiver o streaming de instância desativado, considere atualizar sua experiência para suportá-la, especialmente se o seu mundo 3D for grande.A transmissão de instâncias é baseada na distância no espaço 3D, então mundos maiores naturalmente se beneficiam mais dela.
Se a transmissão de instâncias estiver habilitada, você pode aumentar a agressividade dela. Por exemplo, considere:
- Reduzindo o uso do persistente StreamingIntegrity .
- Reduzindo o raio de streaming .
Para mais informações sobre opções de streaming e seus benefícios, veja Propriedades de Streaming.
Outros problemas comunes
- Duplicação de recursos - Um erro comum é carregar o mesmo recurso várias vezes resultando em diferentes IDs de recurso.Isso pode levar ao mesmo conteúdo sendo carregado na memória várias vezes.
- Volume excessivo de recursos - Mesmo que os recursos não sejam idênticos, há casos em que oportunidades de reutilizar o mesmo recurso e economizar memória são perdidas.
- Arquivos de áudio - Arquivos de áudio podem ser um contribuinte surpreendente para o uso de memória, especialmente se você carregar todos eles no cliente de uma só vez, em vez de carregar apenas o que você precisa para uma parte da experiência.Para estratégias, veja Tempos de carregamento.
- Texturas de alta resolução - O consumo de memória gráfica para uma textura não está relacionado ao tamanho da textura no disco, mas sim ao número de pixels na textura.
- Por exemplo, uma textura de 1024x1024 píxeis consome quatro vezes a memória gráfica de uma textura de 512x512.
- Imagens carregadas no Roblox são transcodificadas para um formato fixo, então não há nenhum ganho de memória ao carregar imagens em um modelo de cores associado a menos bytes por pixel.Da mesma forma, compactar imagens antes de carregar ou remover o canal alfa de imagens que não precisam dela pode diminuir o tamanho da imagem no disco, mas nem melhora nem melhora minimamente o uso de memória.Embora o motor reduza automaticamente a resolução da textura em alguns dispositivos, a extensão da redução depende das características do dispositivo e a resolução excessiva da textura ainda pode causar problemas.
- Você pode identificar o consumo de memória gráfica para uma dada textura expandindo a categoria Textura Gráfica no Console de Desenvolvedor .
Mitigação
- Apenas faça o upload de recursos uma vez - Reutilize o mesmo ID de recurso em objetos e garanta que os mesmos recursos, especialmente malhas e imagens, não sejam carregados separadamente várias vezes.
- Encontre e corrija recursos duplicados - Procure por partes e texturas de malha idênticas que são carregadas várias vezes com IDs diferentes.
- Embora não haja API para detectar semelhança de recursos automaticamente, você pode coletar todos os IDs de recurso de imagem em seu local (manualmente ou com um script), baixá-los e compará-los usando ferramentas de comparação externas.
- Para peças de malha, a melhor estratégia é tomar IDs de malha exclusivos e organizá-los por tamanho para identificar manualmente itens duplicados
- Em vez de usar texturas separadas para diferentes cores, faça o upload de uma textura única e use a propriedade 2 para aplicar várias tonalidades a ela
- Importando recursos em mapa separadamente - Em vez de importar um mapa inteiro de uma só vez, importe e reconstrói recursos no mapa individualmente e reconstrói-los.O importador 3D não faz nenhuma de-duplicação de malhas, então, se você importar um grande mapa com muitas telhas separadas, cada uma dessas telhas seria importada como um recurso separado (mesmo que sejam duplicadas).Isso pode levar a problemas de desempenho e memória ao longo da linha, pois cada malha é tratada individualmente e ocupa memória e chamadas de desenho.
- Limite os pixels das imagens a não mais do que a quantidade necessária.A menos que uma imagem esteja ocupando uma grande quantidade de espaço físico na tela, ela geralmente precisa de no máximo 512x512 pixels.A maioria das imagens menores deve ter menos de 256x256 pixels.
- Use Folhas de Corte para garantir o máximo de reutilização de textura em mapas 3D.Para etapas e exemplos de como criar folhas de corte, veja Criando Folhas de Corte.
Tempos de carregamento
Muitas experiências implementam telas de carregamento personalizadas e usam o método para solicitar recursos para que imagens, sons e malhas sejam baixados em segundo plano.
A vantagem dessa abordagem é que ela permite que você garanta partes importantes de sua experiência sejam totalmente carregadas sem pop-in.No entanto, um erro comum é sobreutilizar esse método para pré-carregar mais recursos do que são realmente necessários.
Um exemplo de uma má prática é carregar o inteiroWorkspace.Embora isso possa impedir o aparecimento de texturas, aumenta significativamente o tempo de carregamento.
Em vez disso, use apenas ContentProvider:PreloadAsync() em situações necessárias, que incluem:
- Imagens na tela de carregamento.
- Imagens importantes no menu da experiência, como fundos de botão e ícones.
- Recursos importantes na área de início ou de spawning.
Se você precisar carregar um grande número de recursos, recomendamos que você forneça um botão Pular Carregamento .