Voltar ao Blog

Corrigindo a Opção Ausente "Clear Player Data" no Fortnite Creative: Resets em Verse e Recuperação de Estado com Backend Customizado

Publicado em 18 de julho de 2026
Corrigindo a Opção Ausente "Clear Player Data" no Fortnite Creative: Resets em Verse e Recuperação de Estado com Backend Customizado Gerada com a ajuda de IA

Em resumo

Este artigo aborda como contornar o bug da opção ausente de "Clear Player Data" no Fortnite Creative e UEFN através de versionamento de schema manual em Verse. Também detalha como configurar opções locais de persistência no editor para acelerar o ciclo de playtest. Por fim, apresenta o uso de backends externos como o [horizOn](https://horizon.pm) para superar as restrições nativas de persistência de dados em plataformas fechadas.

Seu mapa mais recente do Fortnite Creative ou UEFN está pronto. Você refatorou sua economia, redesenhou seu sistema de classes e otimizou seu gameplay loop. Mas, na hora de publicar, você se depara com um pesadelo que quebra a engine: a opção "Press Triangle to Clear Player Data" desapareceu da tela de confirmação de publicação. Você está encurralado. Seus jogadores estão carregando o mapa com dados de persistência desatualizados, causando stack overflows instantâneos, quest lines quebradas e incompatibilidades de estado (state mismatches) que travam o jogo.

Este problema exato tem atormentado criadores nos fóruns de desenvolvedores da Epic, onde a ausência repentina do botão de reset deixa os usuários sem um mecanismo via UI para limpar estados de produção obsoletos. Quando o schema dos dados de persistência do jogador muda, o backend da Epic tenta mapear os dados serializados antigos para as suas novas estruturas. Se o seu código não for projetado para lidar com essas propriedades incompatíveis de forma elegante, você vai inutilizar (brickar) o estado do jogo para 100% dos jogadores que retornarem.

Neste tutorial, vamos nos aprofundar nos contornos técnicos para esse bug. Mostraremos como construir um sistema robusto de versionamento de schema em Verse, configurar as opções locais do UEFN para limpar estados de teste e explorar como backends externos customizados podem libertar você das limitações de persistência de plataformas fechadas.

A Causa Raiz: Por que Schemas Falham em Upgrades de Versão

No Fortnite Creative e no Unreal Editor for Fortnite (UEFN), os dados persistentes são armazenados na infraestrutura de banco de dados da Epic usando estruturas weak_map. Uma weak_map vincula uma instância de jogador (player) a uma classe customizada marcada com o especificador <persistable>. Ao contrário dos bancos de dados relacionais SQL ou documentais tradicionais, a camada de armazenamento da Epic não executa uma pipeline de migração formal quando você lança uma atualização. Em vez disso, ela tenta desserializar qualquer payload binário existente no cloud save do jogador para a definição atual da classe Verse.

Quando você deleta uma variável, renomeia uma propriedade ou altera um tipo (por exemplo, mudando um campo de int para float), o desserializador encontra uma incompatibilidade. Dependendo da gravidade da alteração, essa divergência de schema resulta em um de três modos de falha:

  • Falhas Silenciosas (Silent Failures): O runtime atribui valores padrão (default) às propriedades modificadas, apagando o progresso de qualquer forma, mas sem crashar.
  • Corrupção de Estado (State Corruption): A aplicação lê estados de memória inválidos ou encontra estruturas de dados inesperadas, disparando erros de lógica em outras partes do código.
  • Crashes Graves em Runtime (Severe Runtime Crashes): O mapa falha ao carregar ou a Verse VM interrompe a execução porque não consegue descompactar o mapa persistente.

Quando o botão "Clear Player Data" do console de publicação desaparece, você perde a capacidade de limpar os dados globalmente. Se um desenvolvedor fizer alterações fundamentais no layout de seus dados salvos, o jogo fica quebrado.

A Solução Manual: Versionamento de Schema dentro do Verse

Como você não pode contar com o portal de publicação da Epic para limpar os dados, é necessário implementar um fallback em nível de software. A estratégia é direta: introduzir um rastreador de versão diretamente em suas classes persistíveis. Ao comparar a versão salva do jogador com a versão ativa da aplicação no início da sessão, você pode identificar saves desatualizados e sobrescrevê-los com valores padrão.

Aqui está uma implementação em Verse pronta para produção que configura uma camada de persistência com controle de versão.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Playspaces }
using { /Verse.org/Simulation }

# A simple persistable class representing our player save schema.
# Note: Classes tagged with <persistable> can only contain certain types like int, float, string, and maps.
player_save_data := class<persistable>:
    # The SchemaVersion tracks which generation of player data this struct belongs to.
    SchemaVersion : int = 0
    GoldCount : int = 0
    XP : int = 0
    HasCompletedTutorial : int = 0  # Using int as a boolean flag representation for older Verse constraints

# The persistence manager device handles loading, validating, and migrating player data.
persistence_manager_device := class(creative_device):

    # By updating this value in the Editor, we force a schema migration next time the game runs.
    @editable
    TargetSchemaVersion : int = 2

    # Map to store player data in memory
    var PlayerDataMap : weak_map(player, player_save_data) = map{}

    # Initialize the persistence logic for a joining player
    InitializePlayer(Player : player) : void =
        # Check if the player already has persistent data
        if (ExistingData := PlayerDataMap[Player]):
            # If the stored version is older than our target version, trigger a manual reset
            if (ExistingData.SchemaVersion < TargetSchemaVersion):
                Print("Data version mismatch. Local: {ExistingData.SchemaVersion}, Target: {TargetSchemaVersion}. Resetting player data.")
                ResetPlayerData(Player)
            else:
                Print("Loaded existing player data. Version: {ExistingData.SchemaVersion}")
        else:
            # If no data exists, initialize a new record with the current version
            Print("No player data found. Initializing new record.")
            ResetPlayerData(Player)

    # Re-initializes a player's record with default values at the current version
    ResetPlayerData(Player : player) : void =
        NewData := player_save_data:
            SchemaVersion := TargetSchemaVersion
            GoldCount := 0
            XP := 0
            HasCompletedTutorial := 0

        # Save the freshly initialized data block to the persistence map
        if (set PlayerDataMap[Player] = NewData):
            Print("Successfully saved fresh persistent data block.")

Desconstruindo o Script de Versionamento

Este padrão se baseia em uma validação precoce dentro do método InitializePlayer. A lógica passo a passo funciona da seguinte forma:

  1. A Verificação de Entrada (Entry Check): Quando um jogador entra, o sistema consulta o PlayerDataMap em busca de uma instância existente de player_save_data.
  2. A Avaliação de Versão (Version Assessment): Se um estado de save existir, a engine verifica sua propriedade SchemaVersion.
  3. O Gatilho de Migração (Migration Trigger): Se SchemaVersion for menor do que a propriedade @editable TargetSchemaVersion do dispositivo, o script chama ResetPlayerData(Player).
  4. Sobrescrita de Estado (State Overwrite): ResetPlayerData constrói uma nova instância de player_save_data configurada com o novo TargetSchemaVersion e atualiza a map.

Ao incrementar manualmente o TargetSchemaVersion na configuração do seu dispositivo dentro do UEFN, você força uma limpeza de dados para todos os jogadores na inicialização da próxima sessão, tornando irrelevante o botão ausente na UI da Epic.

Procedimento de Teste Passo a Passo

Para validar com segurança este script de migração em seu ciclo de playtest, siga estes passos sequenciais:

  1. Arraste seu persistence_manager_device customizado para o viewport do seu nível no UEFN.
  2. No painel Details do UEFN, defina o TargetSchemaVersion inicial como 1.
  3. Inicie uma sessão de jogo, acumule alguma pontuação ou ouro e encerre o jogo.
  4. De volta ao editor, atualize o campo TargetSchemaVersion no dispositivo de 1 para 2.
  5. Inicie a sessão novamente. Observe a saída do console log: 'Data version mismatch. Local: 1, Target: 2. Resetting player data.'
  6. Verifique se o ouro e a progressão do seu jogador foram resetados de forma limpa, sem crashar a Verse VM.

Configurações de Desenvolvimento Local: Ignorando Arquivos de Save Durante a Iteração

Embora o versionamento de código em runtime resolva problemas em servidores de produção (live servers), ele adiciona uma fricção indesejada durante o playtesting local. Mudar manualmente o número da versão dentro do UEFN toda vez que você modifica uma feature em andamento é tedioso. Para otimizar seu processo de debugging, você pode ignorar completamente a persistência local através das configurações do seu editor.

Siga estes passos para desabilitar a persistência local:

  1. No UEFN, navegue até Island Settings no painel Outliner.
  2. Busque pela subseção User Options - Game Rules.
  3. Localize a opção Enable Persistence e desabilite-a.
  4. Se estiver testando loops multiplayer localmente, abra as Editor Preferences, vá para o menu In-Game Play e localize a caixa de seleção Clear Local Saved Data On Launch. Marcar essa opção garante que cada simulação comece com um cache vazio.

Limitações de Persistência Nativas do UEFN

Usar a camada de persistência nativa do Verse traz restrições arquiteturais significativas. Mesmo quando as opções de limpeza em nuvem (cloud-clear) funcionam perfeitamente, os desenvolvedores estão limitados por restrições rígidas da plataforma:

Para minijogos casuais, esses limites são gerenciáveis. Mas para RPGs persistentes complexos, shooters live-ops ou títulos multiplataforma, depender exclusivamente da persistência proprietária de ciclo fechado bloqueia seu caminho de escalabilidade.

    # This keeps the server-side payload lightweight (under 240 bytes) 
    # while securing long-term storage off the Fortnite engine.

## Melhores Práticas para Gerenciamento de Persistência de Estado de Jogo

Quer você prefira os maps nativos do Verse ou aproveite uma arquitetura de servidor externa, manter um ciclo de vida de persistência estável é vital para jogos multiplayer. Siga estes princípios para proteger os estados dos jogadores:

1. **Implemente Versionamento Implícito Cedo:** Sempre inclua um inteiro `SchemaVersion` no layout inicial de seus dados salvos. Mesmo se você não planeja modificar seu schema, ter a chave de versão desde o primeiro dia evita corrupção catastrófica de dados no futuro.
2. **Imponha Regras de Validação de Estado:** Ao ler o estado carregado, valide os limites de cada atributo. Se a quantidade de ouro salva de um jogador for negativa ou exceder o limite estrutural do seu map, resete essa propriedade específica para evitar exploits na economia.
3. **Minimize a Frequência de Saves:** Gravar na nuvem é custoso. Em vez de atualizar o banco de dados a cada moeda coletada, agrupe seus writes em lotes (batch). Dispare os saves durante marcos importantes, como a finalização da partida, level-up do jogador ou quando o jogador sai da sessão.
4. **Construa Estruturas de Fallback Limpas:** Nunca permita que uma leitura com falha impeça um jogador de entrar no jogo. Se o payload de persistência falhar ao desserializar, recorra imediatamente a uma estrutura de estado padrão (default).
5. **Desacople o Código de Gameplay da Lógica de Armazenamento:** Mantenha suas consultas de armazenamento isoladas em um dispositivo gerenciador de persistência dedicado. Seus dispositivos de armas, progressão e UI devem consultar este gerenciador em vez de fazer chamadas diretas ao data map.

## Próximos Passos

Depender da UI do console da Epic para gerenciar migrações de estado críticas é um padrão de design arriscado. Quando a opção "Clear Player Data" falha, o versionamento em runtime dentro do Verse funciona como sua primeira linha de defesa. No entanto, se o seu jogo exige saves de alta frequência, telemetria complexa ou controle administrativo completo, migrar seu banco de dados para um backend dedicado é a solução definitiva.

---

Fonte: [clear players data button in creative 1](https://forums.unrealengine.com/t/clear-players-data-button-in-creative-1/2735737)