Voltar ao Blog

Como dominar o Asset Stripping no Unreal Engine Dedicated Server (Passo a passo)

Publicado em 17 de março de 2026
Como dominar o Asset Stripping no Unreal Engine Dedicated Server (Passo a passo)

Você inicia seu Unreal Engine dedicated server recém-compilado, esperando um processo leve e headless. Você faz um memory profile e lá estão eles: milhares de objetos UMaterial, UTexture e USoundWave ocupando a RAM do seu servidor.

A documentação oficial afirma que um servidor headless não renderiza visuais. Então, por que seu servidor está acumulando megabytes de dados de textura?

Todo desenvolvedor indie conhece o momento em que os custos de hosting começam a ameaçar o projeto. Quando uma máquina bare-metal só consegue hospedar 10 instâncias do seu jogo em vez de 50 devido ao memory bloat, sua arquitetura de backend está comprometida.

Neste mergulho técnico, vamos dissecar como o unreal engine dedicated server asset stripping realmente funciona, por que ghost assets permanecem na memória e como você pode arquitetar seu C++ e Blueprints para erradicá-los completamente.

A Anatomia de um "Ghost Asset" em um Dedicated Server

Para corrigir o problema, você deve entender o que o Unreal Automation Tool (UAT) faz ao realizar o cook para o target Server.

Quando um desenvolvedor vê UTexture ou UMaterial em um perfil de memória de servidor, a primeira suposição é que o engine falhou no stripping. Isso é apenas parcialmente verdade.

O Unreal Engine separa os assets em duas partes:

  1. O UObject Wrapper: Metadados, propriedades e dados de reflexão.
  2. O Bulk Data: A carga pesada real (pixels comprimidos DXT para texturas, vertex buffers para meshes, dados PCM para áudio).

Ao cozinhar um dedicated server, o cooker remove com sucesso o bulk data. Os dados de renderização somem. No entanto, o wrapper UObject permanece.

Se um Blueprint Class Default Object (CDO) tem uma hard reference para uma UTexture2D, o servidor precisa instanciar o UObject UTexture2D para satisfazer o sistema de reflexão e evitar crashes. Mesmo que o bulk data tenha sido removido e a textura ocupe apenas 1KB em vez de 10MB, o overhead de instanciar 50.000 desses UObjects resulta em um memory bloat significativo e sobrecarga no Garbage Collection.

Áudio e Partículas seguem a mesma lógica?

Sim. Se você tiver uma hard reference para um USoundCue ou UNiagaraSystem, o servidor carregará o UObject. Os dados pesados de áudio PCM são removidos, mas o objeto existe.

Com sistemas de partículas, isso é perigoso. Se houver lógica de CPU (como simulações Niagara complexas), o servidor pode executar o tick dessa lógica se não for configurado corretamente, consumindo CPU e memória.

Passo 1: Profiling do Memory Bloat do Servidor

Antes de mexer no código, você precisa de números. Você não otimiza o que não mede.

Inicie seu dedicated server com os argumentos:

-LLM -LLMCSV -memoryprofiler

No console do servidor, execute:

memreport -full

Procure por Obj List no arquivo .memreport. Você verá algo como:

Class UTexture2D: 1452 Objects, 1.25 MB
Class UMaterial: 840 Objects, 0.85 MB
Class USoundWave: 620 Objects, 0.45 MB

Embora 2.5MB pareça pouco, o alinhamento de memória e as dependências em cascata podem inflar um servidor de 150MB para mais de 600MB.

Confira nossa análise sobre arquitetura de servidores zero-waste.

Passo 2: Cortando Hard References com Soft Pointers

A causa principal de ghost assets são hard references. Se seu ACharacter tem um hard pointer para um retrato de UI, o servidor carregará esse asset.

A solução em C++: TSoftObjectPtr

Substitua referências visuais/áudio por soft references. Elas armazenam apenas o caminho do asset; o UObject só é carregado ao chamar LoadSynchronous() ou usar o Streamable Manager.

RUIM: Hard Reference (Carrega no Servidor)

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI")
UTexture2D* HeroPortrait;

BOM: Soft Reference (Servidor Limpo)

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI")
TSoftObjectPtr<UTexture2D> HeroPortraitSoft;

Passo 3: Forçando NeedsLoadForServer

Você pode ignorar componentes visuais sobrescrevendo NeedsLoadForServer.

bool UMyVisualCustomizationComponent::NeedsLoadForServer() const
{
    return false; // Garante que o componente seja removido da memória do servidor
}

Passo 4: Stripping via Configuração

No DefaultEngine.ini, exclua diretórios do cook:

[/Script/UnrealEd.ProjectPackagingSettings]
+DirectoriesToNeverCook=(Path="UI/Widgets")

No YourGameServer.Target.cs, desative o áudio engine:

bDisableAudio = true; 

Melhores Práticas

  1. Separar Meshes de Colisão de Visuais: Use um UStaticMesh simples para o servidor.
  2. Auditar Construction Scripts: Use Switch Has Authority para evitar que o servidor instancie visuais.
  3. Isolar Data Assets: Separe stats (servidor/cliente) de visuais (apenas cliente).
  4. Automatizar Profiling no CI/CD: Verifique a memória em cada build.

Escalando seu Backend

Reduzir o footprint do servidor de 800MB para 180MB permite hospedar 4-5 vezes mais instâncias, cortando custos de AWS ou Google Cloud.

Orquestrar esses servidores é difícil. Com horizOn, esses serviços vêm pré-configurados. Foque no seu jogo enquanto o horizOn cuida do auto-scaling global.

Conclusão

O asset stripping no Unreal Engine depende da sua arquitetura. Usando soft pointers e separando dados visuais, você obtém a performance necessária para o multiplayer.

Pronto para escalar? Teste o horizOn grátis ou veja nossa documentação da API.


Fonte: Stripping asset on dedicated server