Dicas para trabalhar de forma mais eficaz com o Banco de Dados de Ativos

JAVIER ABUD / UNITY TECHNOLOGIESContributor
Oct 6, 2020|10 Min
Dicas para trabalhar de forma mais eficaz com o Banco de Dados de Ativos
Esta página da Web foi automaticamente traduzida para sua conveniência. Não podemos garantir a precisão ou a confiabilidade do conteúdo traduzido. Se tiver dúvidas sobre a precisão do conteúdo traduzido, consulte a versão oficial em inglês da página da Web.

O Asset Import Pipeline v2 é o novo pipeline de ativos padrão no Unity, substituindo o Asset Import Pipeline v1 por um banco de dados de ativos reescrito para permitir uma rápida troca de plataforma. Ele estabelece as bases para importações de ativos escaláveis com rastreamento de dependência robusto. Continue lendo para explorar como o Banco de Dados de Ativos funciona e descubra algumas dicas para economizar tempo.

Desde o lançamento do Unity 2019.3, o novo Asset Import Pipeline tem sido o pipeline padrão para novos projetos. Combinado com muitas outras melhorias, isso estabelece a base para um pipeline de importação de ativos mais confiável, eficiente e escalável. Essa reescrita alterou a maneira como a pasta Biblioteca funciona para oferecer suporte a novos fluxos de trabalho.

Vamos dar uma olhada em algumas situações que você pode encontrar e como gerenciá-las de forma eficiente. Você aprenderá a identificar e resolver alguns dos gargalos que custam tempo e desempenho do projeto.

As dicas que você encontrará aqui se aplicam ao Unity 2019.3 e versões posteriores. Lembre-se, se o seu projeto estiver em produção além da prototipagem, para máxima estabilidade, recomendamos que você use a versão mais recente de Suporte de Longo Prazo (LTS) do Unity, Unity 2019 LTS.

Explore os tempos de importação como um ponto de partida para otimização

Primeiro, vamos falar sobre algumas coisas que acontecem quando você cria um novo projeto ou abre um projeto em que sua Biblioteca de ativos ainda não está presente.

Se você olhar o arquivo Editor.log , notará muitas linhas parecidas com:

  • Comece a importar…
  • Importação concluída…

É assim que o Asset Import Pipeline deixa um rastro de suas operações para que elas possam ser inspecionadas posteriormente.

Você pode usar essas informações para descobrir um certo tipo de gargalo, ou seja, Tempos de Importação de Ativos.

Ao analisar a saída de cada linha, você pode extrair os seguintes dados:

  • Caminho do ativo
  • Duração da importação
  • Extensão de arquivo

Analisando esses dados, podemos categorizá-los por extensão. Depois de saber qual importador importou qual ativo, você pode agregar esses dados em um gráfico de pizza mostrando quais tipos de ativos demoram mais para serem importados. Por exemplo:

Diagrama de distribuição de importação categorizada

Esses dados podem lhe dar uma imagem mais clara de onde estão os gargalos do seu projeto.

Neste exemplo específico, texturas, modelos e prefabs são os que mais consomem tempo, fornecendo um ponto de partida para investigar quais ativos podem ser otimizados.

O SimpleEditorLogParser

Baixe este projeto de exemplo SimpleEditorLogParser e use-o como base para seu próprio analisador.

Ser capaz de ver qual categoria de ativos leva mais tempo para importar pode ajudar você a planejar onde direcionar seus esforços de otimização. Se a importação de texturas for a categoria que leva mais tempo, examine as texturas que demoram mais para serem importadas e considere remover as texturas que não deveriam aparecer na compilação final.

Isso não só acelerará seus tempos de importação, mas também melhorará o desempenho do seu pipeline de integração contínua se você estiver fazendo compilações noturnas limpas ou algo semelhante.

Como criar perfis de tempos de inicialização para rastrear gargalos

É importante poder abrir seus projetos rapidamente. Os minutos necessários para reiniciar o Editor ou abrir vários projetos ao longo do dia podem representar uma perda de tempo valiosa.

À medida que um projeto se torna mais complexo e usa mais recursos, ele demora mais para ser aberto. Isso pode ocorrer devido a uma grande quantidade de fatores e, antes do Unity 2019.3, não havia como colocar o profiler em funcionamento enquanto o Editor era iniciado.

Um argumento de linha de comando para criar um perfil no lançamento

Entre os vários argumentos de linha de comando que você pode fornecer ao abrir o Unity, o argumento de linha de comando -profiler-enable permite que você crie um perfil do Editor durante a inicialização.

Este comando informa ao Editor para começar a gravar dados de criação de perfil para o primeiro quadro do aplicativo, que é todo o código executado até que o Editor fique visível. Usar esse argumento pode ajudar você a ver o que acontece durante a inicialização e o que leva tempo. Você pode ver se é um sistema no Unity, um pacote da Asset Store ou um código específico para seu projeto. Isso pode ajudar você a descobrir o que fazer em seguida.

Imagem

Nesta captura, você pode ver que abrir este projeto específico leva cerca de 50 s.

À primeira vista, parece levar 43 s para carregar o AssetDatabase. Após uma inspeção mais detalhada, fica claro que 14 s são gastos em chamadas para OnPostProcessAllAssets. Mais adiante, o código executado durante RegisterScriptsAndTryLoadingExistingUserAssemblies soma 10 s, e 5,7 s disso são para carregar o Domínio, que fica ainda mais lento por chamadas para Scripts que têm o atributo [InitializeOnLoad] .

Esses dados de inicialização podem ajudar você a rastrear gargalos de desempenho e ver se o código está no seu projeto ou no próprio Unity .

Como encontrar o resultado da importação no disco

A pasta Biblioteca agora pode conter vários resultados de importação para o mesmo ativo, portanto, os projetos que usam o novo Pipeline de importação de ativos não têm mais um mapeamento “simples” de GUID (identificador global exclusivo) para pasta na pasta Biblioteca.

Os arquivos na pasta Biblioteca são baseados no hash de seu conteúdo, além de uma série de dependências estáticas e dinâmicas. Isso permite que o Unity tenha recursos como troca rápida de plataforma, desduplicação de ativos e pular uma importação se o hash de um ativo já estiver presente na pasta Biblioteca.

Isso significa que não é mais trivial encontrar resultados de importação na pasta Biblioteca. Aqui está um exemplo que mostra onde você pode encontrar o resultado da importação de “Assets/Prefabs/MyPrefab.prefab”:

public class LibraryPathsForAsset
{
    [MenuItem("AssetDatabase/OutputLibraryPathsForAsset")]
    public static void OutputLibraryPathsForAsset()
    {
        var assetPath = "Assets/Prefabs/MyPrefab.prefab";

        StringBuilder assetPathInfo = new StringBuilder();

        var guidString = AssetDatabase.AssetPathToGUID(assetPath);
        //The ArtifactKey is needed here as there are plans to
        //allow importing for different platforms without switching
        //platform, thus ArtifactKeys will be parametrized in the future
        var artifactKey = new ArtifactKey(new GUID(guidString));
        var artifactID = AssetDatabaseExperimental.LookupArtifact(artifactKey);

       //Its possible for an Asset to have multiple import results,
       //if, for example, Sub-assets are present, so we need to iterate
        //over all the artifacts paths
        AssetDatabaseExperimental.GetArtifactPaths(artifactID, out var paths);

        assetPathInfo.Append($"Files associated with {assetPath}");
        assetPathInfo.AppendLine();

        foreach (var curVirtualPath in paths)
        {
            //The virtual path redirects somewhere, so we get the
            //actual path on disk (or on the in memory database, accordingly)
            var curPath = Path.GetFullPath(curVirtualPath);
            assetPathInfo.Append("\t" + curPath);
            assetPathInfo.AppendLine();
        }

        Debug.Log("Path info for asset:\n"+assetPathInfo.ToString());
    }
}
Obter exemplos de gists do GitHub

Aqui estão dois resumos para diferentes versões do Unity:

Os exemplos são diferentes porque, conforme a implementação do Asset Import Pipeline amadureceu, várias APIs foram movidas do namespace Experimental para o próprio namespace do AssetDatabase.

Como encontrar ativos mais rápido

Muitas vezes, você pode querer encontrar um recurso específico em seu projeto e fazer algo com o resultado. Talvez você queira fazer isso várias vezes quando estiver executando o código do Editor.

A abordagem da força bruta

Chamar AssetDatabase.FindAssets percorrerá todo o projeto para corresponder à consulta que você forneceu a ele. À medida que os projetos ficam maiores, isso pode se tornar um gargalo de desempenho, pois o tempo necessário para pesquisar projetos de tamanhos diferentes cresce linearmente.

Diagrama de tempo decorrido versus ativos totais

Como esperado, quanto mais ativos um projeto tiver, maior será o tempo para pesquisá-los. Felizmente, o tempo para encontrar cada ativo permanece relativamente estável ao longo do tempo.

Imagem

Como você pode ver, se seu projeto tiver centenas de milhares de ativos, a busca por ativos pode levar a uma desaceleração perceptível no desenvolvimento. Com 200.000 ativos, já há um atraso de 200 ms para uma consulta de pesquisa simples.

Usar a abordagem de força bruta produz este padrão de uso comum:

string[] assets = AssetDatabase.FindAssets ("t:texture2D");

if(assets.Length > 0)
{
    string path = AssetDatabase.GUIDToAssetPath (guids[0]);
    if (!string.IsNullOrEmpty (path))
    {
        Texture tex = AssetDatabase.LoadAssetAtPath<Texture>(path);
        //Do something with this texture
    }
}


Basicamente, esse código percorre todo o projeto para encontrar uma textura e então fazer algo com ela.

Pesquisa escalável

O AssetDatabase fornece uma maneira de pesquisar o caminho de um ativo por GUID. Você pode pensar nisso como procurar algo em um dicionário por chave, em vez de iterar uma matriz para encontrar uma correspondência.

O benefício de usar essa abordagem em vez da força bruta é que o AssetDatabase não precisa examinar todo o projeto para encontrar o ativo. Ele pode simplesmente usar o GUID como um índice de banco de dados e seguir esse caminho para carregar o ativo na memória.

Como posso encontrar o GUID?

Você pode encontrar o GUID no arquivo .meta correspondente de um ativo, por exemplo:

fileFormatVersion: 2
guia: 9fc0d4010bbf28b4594072e72b8655ab
Importador Padrão:
objetos externos: {}
userData:
assetBundleName:
assetBundleVariant:

Neste caso, o GUID para este ativo é 9fc0d4010bbf28b4594072e72b8655ab.

Com essas informações, você pode fazer o seguinte:

var path = AssetDatabase.GUIDToAssetPath("9fc0d4010bbf28b4594072e72b8655ab");
var asset = AssetDatabase.LoadAssetAtPath<Texture>(path);

Agora seu ativo está pronto para ser usado.

Acelerando a pesquisa com Quick Search e TypeCache

Como observação, se você estiver interessado em acelerar a pesquisa no Editor, você também deve estar ciente das seguintes ferramentas:

Pacote de pesquisa rápida que permite pesquisar em diversas áreas do Unity.

TypeCache para procurar scripts derivados de um tipo que você conhece.

O que fazer se o GUID mudar

Normalmente, o GUID de um ativo é constante.

Entretanto, em certas situações, um ativo e seu arquivo .meta são duplicados, causando um conflito que o AssetDatabase resolve das seguintes maneiras:

Se você duplicar uma pasta dentro de um projeto para outro lugar no mesmo projeto

Importando um pacote do Asset Store várias vezes ou copiando uma pasta de outro projeto várias vezes para o seu projeto

Coisas que levam à atualização lenta

Quando AssetDatabase.Refresh é executado, muitos sistemas precisam trabalhar juntos para apresentar seu projeto em um estado válido. Na minha palestra no Unite Copenhagen, detalho as várias etapas do que acontece quando o Refresh é chamado.

Retornos de chamada específicos executados durante uma atualização interagem com o código. Isso pode afetar o tempo que a operação de atualização leva para ser concluída.

Preste atenção aos retornos de chamada que ocorrem durante o Domain Reload

Quanto mais código for executado durante uma Recarga de Domínio, mais lenta será sua experiência no Editor. Para permanecer no fluxo ao iterar no código, pense cuidadosamente sobre quando o código deve ser executado e se ele pode ser adiado para mais tarde no projeto.

Durante uma recarga de domínio, seu código será executado se contiver qualquer um dos seguintes métodos:

1. Acordado

2. Ativar

3. Ao validar

O ideal é que seu código nesses métodos seja muito rápido ou seja adiado para execução em outro momento (não durante uma atualização, por exemplo). Isso ocorre porque esses retornos de chamada devem ajudar a restaurar determinados estados, mas como não há restrições sobre o que pode ser feito nessas chamadas, qualquer código que não seja escalável (ou seja, qualquer coisa que atravesse o projeto inteiro) diminui a velocidade de iteração dos scripts enquanto o Editor estiver aberto.

Outra abordagem é usar EditorApplication.delayCall, onde seu código é executado no próximo tick do Editor após o AssetDatabase ter a chance de detectar e importar todas as alterações no disco.

Siga este tópico nos fóruns do Unity para se manter atualizado com notícias sobre melhorias nesta área.

Conclusão

Espero que essas dicas tenham sido úteis. Conte-nos o que mais você gostaria de saber sobre o Asset Import Pipeline ou quais são seus pontos fracos. Estamos trabalhando ativamente para melhorar o Pipeline de importação de ativos e queremos tornar sua iteração o mais instantânea possível, para que você possa ser mais produtivo ao trabalhar com o Editor e alterar ativos e/ou scripts.