Unity 6.6 reforma os AssetBundles: compilação incremental de Slime Rancher 2 caiu de 32 minutos para três
A Unity lançou na versão 6.6 as content directories — uma nova forma de empacotar e carregar conteúdo que os programadores do motor apelidam abertamente de substituta dos AssetBundles. A principal diferença está em que o runtime passa a endereçar, carregar e descarregar artefactos individuais — uma malha ou uma textura concretas, por exemplo — e não o bundle inteiro. A composição dos bundles, para a qual as equipas passaram anos a inventar estratégias de agrupamento, deixa de ser uma decisão de design.
A Unity apresenta números de um projeto real: Slime Rancher 2, migrado de Addressables para content directories. A compilação incremental desceu de 32 minutos e 16 segundos para 3 minutos e 4 segundos; a compilação limpa, de 58 minutos e 6 segundos para 37 minutos e 13 segundos. O tamanho do jogo compilado emagreceu de 4 GB para 2,88 GB e o carregamento acelerou de 45 para 30 segundos — cerca de um terço. As medições foram feitas no Unity 6.6 Beta (6000.6.0b10) num MacBook Pro com M5 Max.
Porque é que o bundle enquanto unidade de carregamento deixou de servir
Um AssetBundle é uma unidade indivisível de distribuição, armazenamento e carregamento. As dependências são seguidas ao nível do bundle, e é preciso carregá-lo e descarregá-lo por inteiro. Daí todo o trabalho que o acompanha: distribuir manualmente os assets por grupos, seguir cadeias de dependências, combater a duplicação de recursos comuns entre bundles.
As content directories são construídas de outra maneira. A Unity usa um esquema de armazenamento endereçável por conteúdo — a mesma ideia que está na base do git: cada ficheiro de conteúdo é nomeado e endereçado por um hash do seu próprio conteúdo. A desduplicação deixa de ser tarefa do programador e passa a ser uma propriedade do formato. Ainda assim, os artefactos referenciam-se entre si não por hash, mas por identificadores estáveis — caso contrário, editar um único ficheiro alteraria em cascata os hashes de toda a cadeia; a correspondência entre identificadores e hashes fica guardada no manifesto da compilação.
O que entra na compilação passa a ser definido não por uma marcação de cada asset, mas por assets raiz — ScriptableObject vulgares. As dependências são puxadas automaticamente e seguidas por asset individual, e não por bundle. No código surge o tipo Loadable<T>
— uma referência carregável ao nível do motor: declara-se um campo do género Loadable<Mesh> bodyMesh e depois chama-se bodyMesh.Load(); carregar e descarregar assets individuais pode fazer-se de forma síncrona ou assíncrona, através de async/await. Os objetos referenciados por um Loadable entram na compilação, mas não são carregados para memória até serem pedidos. O carregamento em si é totalmente assíncrono tanto na leitura como na desserialização, recorrendo às API assíncronas de cada plataforma; na base está o formato de ficheiros de conteúdo que surgiu no DOTS em 2022.O que fazer quem já está em Addressables
A Unity não partiu os projetos existentes. As content directories são compatíveis com o pacote Addressables, que continua a ser a interface para organizar conteúdo, e os projetos existentes podem ser convertidos para o novo backend: Slime Rancher 2 foi migrado sem uma única alteração de código. O procedimento de conversão e a comparação das opções estão descritos na documentação do Addressables.
O que muda é a própria abordagem ao que é preciso marcar. A Unity inclui automaticamente na compilação os assets referenciados por um Loadable e elimina sozinha os duplicados, pelo que deixam de ser necessários bundles separados para as dependências comuns. A documentação recomenda criar um único asset raiz para todo o projeto e, se o código carregar muitos assets por chaves de texto, usar um ScriptableObject como lista de assets em vez de múltiplas raízes.
Limitações que convém conhecer de antemão
Na 6.6 as content directories só funcionam com conteúdo local — aquele que segue junto com o player. Para a entrega remota e para as descargas após a instalação continuam a ser necessários AssetBundles ou um mecanismo próprio. Uma entrega granular «pelo ar» a sério é prometida pela Unity para a geração Unity 7, com pormenores em 2027.
- a API BuildUsage
Uma content directory é registada no runtime, após o que os seus assets ficam disponíveis; as cenas também são ligadas através de referências carregáveis. Os pormenores estão descritos na documentação oficial da Unity sobre content directories.
Porque é que a Unity precisou de mudar os alicerces justamente agora
As content directories parecem uma troca de apoio de toda a pilha de conteúdo e não uma funcionalidade avulsa da 6.6. As limitações do AssetBundle adivinham-se também no desenho do Addressables: uma parte considerável do trabalho com esse pacote resumia-se a compensar a indivisibilidade do bundle. Se a unidade base se torna atómica, parte das tarefas habituais dos artistas técnicos e dos engenheiros de build — a distribuição por grupos, a caça aos duplicados, a gestão manual das cadeias de dependências — perde sentido por si só.
A direção coincide com o movimento geral da indústria rumo a armazenamentos endereçáveis por conteúdo e a compilações incrementais: o mesmo princípio funciona há muito nos sistemas de controlo de versões e nas caches de compilação e, em projetos grandes, compensa sobretudo no tempo de iteração. A redução para um décimo da compilação incremental no exemplo de Slime Rancher 2 atinge não tanto a build final como o ciclo diário de editar e verificar — e é aí que as equipas gastam as suas horas de trabalho.
O Addressables, por seu lado, não vai a lado nenhum: a julgar pela forma como a migração está montada, o pacote continua a ser a interface para o utilizador, enquanto as content directories ocupam o lugar por baixo. Dado que a Unity associa a entrega remota aos novos alicerces na geração Unity 7, a passagem para este backend provavelmente acabará por se tornar condição para a descarga granular de conteúdo, e os projetos que hoje vivem da distribuição manual de bundles fariam bem em olhar para a conversão com antecedência.
Porque é que os AssetBundles só agora foram reformados: a pressão de Godot e Unreal, a dor acumulada do Addressables, uma mudança de rumo após a saída de John Riccitiello?