Torna al Blog

Risolvere l'assenza dell'opzione Clear Player Data in Fortnite Creative: reset in Verse e ripristino dello stato tramite Backend personalizzato

Pubblicato il 19 luglio 2026
Risolvere l'assenza dell'opzione Clear Player Data in Fortnite Creative: reset in Verse e ripristino dello stato tramite Backend personalizzato

In breve

Questa guida affronta il problema dell'opzione mancante 'Clear Player Data' nella console di Epic per Fortnite Creative e UEFN, che impedisce il reset dei dati dei giocatori durante le modifiche dello schema di persistenza. Viene illustrata un'implementazione pratica in Verse per gestire lo schema versioning a livello applicativo e aggirare il problema. Vengono inoltre descritte le impostazioni locali per disabilitare la persistenza durante il debug e presentati i vantaggi della migrazione verso un Backend esterno come horizOn.

La vostra ultima mappa di Fortnite Creative o UEFN è pronta. Avete effettuato il refactoring dell'economia, riprogettato il sistema delle classi e ottimizzato il gameplay loop. Ma al momento della pubblicazione, vi scontrate con un incubo che blocca l'engine: l'opzione "Press Triangle to Clear Player Data" è svanita dalla schermata di conferma della pubblicazione. Siete bloccati. I vostri giocatori caricano la mappa con dati di persistenza obsoleti, causando stack overflow immediati, quest line interrotte e disallineamenti di stato che mandano in crash il gioco.

Questo identico problema ha tormentato i creator nei forum degli sviluppatori di Epic, dove l'improvvisa assenza del pulsante di reset lascia privi di un meccanismo basato su interfaccia utente per eliminare gli stati di produzione obsoleti. Quando lo schema dei dati di persistenza dei giocatori cambia, il Backend di Epic tenta di mappare i vecchi dati serializzati sulle nuove strutture. Se il vostro codice non è progettato per gestire questi disallineamenti delle proprietà in modo efficiente, rischierete di compromettere lo stato di gioco per il 100% dei giocatori che ritornano.

In questo tutorial, analizzeremo nel dettaglio i workaround tecnici per questo bug. Vedremo come creare un solido sistema di schema versioning in Verse, come configurare le impostazioni locali di UEFN per cancellare gli stati di test e come i Backend esterni personalizzati possano liberarvi dalle limitazioni della persistenza delle piattaforme chiuse.

The Root Cause: Perché gli schema falliscono negli upgrade di versione

In Fortnite Creative e Unreal Editor for Fortnite (UEFN), i dati persistenti vengono salvati nell'infrastruttura database di Epic utilizzando strutture weak_map. Una weak_map collega un'istanza player a una classe personalizzata contrassegnata dallo specificatore <persistable>. A differenza dei database SQL tradizionali o orientati al documento, il layer di storage di Epic non esegue una pipeline di migrazione formale quando rilasciate un aggiornamento. Al contrario, tenta di deserializzare qualsiasi payload binario presente nel cloud save del player all'interno della definizione corrente della classe Verse.

Quando eliminate una variabile, rinominate una proprietà o cambiate un tipo (ad esempio, modificando un campo da int a float), il deserializzatore rileva un disallineamento. A seconda della gravità della modifica, questa divergenza dello schema si traduce in una di queste tre modalità di errore:

  • Silent Failures: il runtime assegna valori predefiniti alle proprietà modificate, azzerando comunque i progressi ma senza causare crash.
  • State Corruption: l'applicazione legge stati di memoria non validi o incontra strutture dati impreviste, innescando errori logici altrove.
  • Severe Runtime Crashes: la mappa non si carica, o la VM di Verse interrompe l'esecuzione perché non riesce a decomprimere la mappa persistente.

Quando il pulsante "Clear Player Data" della console di pubblicazione scompare, si perde la possibilità di azzerare i dati a livello globale. Se uno sviluppatore apporta modifiche strutturali al layout dei dati di salvataggio, il gioco si rompe.

The Manual Fix: lo Schema Versioning in Verse

Poiché non si può fare affidamento sul portale di pubblicazione di Epic per cancellare i dati, è necessario implementare un fallback a livello software. La strategia è semplice: introdurre un tracciatore di versione direttamente all'interno delle classi persistibili. Confrontando la versione salvata del player con la versione attiva dell'applicazione all'avvio della sessione, è possibile identificare i salvataggi obsoleti e sovrascriverli con valori predefiniti.

Ecco un'implementazione Verse pronta per la produzione che configura un layer di persistenza con controllo di versione.

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.")

Analisi dello script di versioning

Questo pattern si basa su una validazione preventiva all'interno del metodo InitializePlayer. La logica passo-passo è la seguente:

  1. Il controllo iniziale: quando un player si unisce, il sistema interroga PlayerDataMap alla ricerca di un'istanza esistente di player_save_data.
  2. La valutazione della versione: se esiste uno stato di salvataggio, l'engine controlla la sua proprietà SchemaVersion.
  3. Il trigger di migrazione: se SchemaVersion è inferiore alla proprietà @editable TargetSchemaVersion del dispositivo, lo script chiama ResetPlayerData(Player).
  4. Sovrascrittura dello stato: ResetPlayerData crea una nuova istanza di player_save_data impostata sulla nuova TargetSchemaVersion e aggiorna la mappa.

Manualmente incrementando TargetSchemaVersion nella configurazione del dispositivo all'interno di UEFN, forzerete un ripristino dei dati per tutti i giocatori al loro prossimo avvio di sessione, rendendo irrilevante l'assenza del pulsante nell'interfaccia di Epic.

Procedura di test passo dopo passo

Per verificare in sicurezza questo script di migrazione all'interno del vostro ciclo di playtest, seguite questi passaggi in sequenza:

  1. Trascinate il vostro persistence_manager_device personalizzato nella viewport del livello in UEFN.
  2. Nel pannello Details di UEFN, impostate il valore iniziale di TargetSchemaVersion a 1.
  3. Avviate una sessione di gioco, accumulate punteggio o oro, quindi terminate la partita.
  4. Tornati nell'editor, aggiornate il campo TargetSchemaVersion sul dispositivo da 1 a 2.
  5. Avviate nuovamente la sessione. Osservate l'output del log in console: 'Data version mismatch. Local: 1, Target: 2. Resetting player data.'
  6. Verificate che l'oro e i progressi del player siano stati azzerati correttamente, senza mandare in crash la VM di Verse.

Local Development Settings: bypassare i file di salvataggio durante l'iterazione

Sebbene il versioning del codice a runtime risolva i problemi sui server live, introduce un attrito indesiderato durante il playtest locale. Incrementare manualmente il numero di versione all'interno di UEFN ogni volta che si modifica una feature in corso di sviluppo è noioso. Per ottimizzare il processo di debug, potete bypassare completamente la persistenza locale tramite le impostazioni dell'editor.

Seguite questi passaggi per disabilitare la persistenza locale:

  1. In UEFN, andate su Island Settings nel pannello Outliner.
  2. Cercate la sottosezione User Options - Game Rules.
  3. Individuate l'opzione Enable Persistence e disabilitatela.
  4. Se state testando loop multiplayer in locale, aprite Editor Preferences, andate nel menu In-Game Play e cercate la casella di controllo Clear Local Saved Data On Launch. Selezionando questa opzione, vi assicurerete che ogni simulazione inizi con una cache vuota.

Tuttavia, i bypass locali non simulano gli scenari di produzione. Sebbene i tempi di iterazione nei test possano scendere da 45 secondi a meno di 5 secondi disabilitando la cache di persistenza, dovete eseguire almeno un ciclo completo di staging con la persistenza abilitata prima di andare live. È qui che possono sorgere problemi di connessione. I setup di playtest locale sono noti per i conflitti di driver, che fanno perdere tempo prezioso agli sviluppatori nella diagnosi dei driver di rete di Unreal Engine durante i timeout di avvio della sessione UEFN.

UEFN's Built-in Persistence Limitations

L'utilizzo del layer di persistenza nativo di Verse comporta notevoli vincoli architetturali. Anche quando le opzioni di svuotamento sul cloud funzionano perfettamente, gli sviluppatori sono vincolati da rigidi limiti di piattaforma:

  • Storage Budgets: i blocchi di dati persistibili sono limitati a 12KB per player per sessione. Il superamento di questo limite impedisce il salvataggio dello stato.
  • Solo tipi primitivi: non è possibile serializzare classi personalizzate che non siano contrassegnate come <persistable>, né memorizzare riferimenti a game object (come creative_device o actor dinamici).
  • Nessuna query esterna: il sistema di Epic è una black box completa. Non è possibile interrogare i dati dei player da una dashboard esterna, verificare gli stati degli utenti per rilevare exploit o migrare i database in modo dinamico.
  • Colli di bottiglia della telemetria: la progettazione di dashboard analitiche complesse in UEFN è fortemente limitata dai vincoli di lunghezza delle stringhe. Ad esempio, gli sviluppatori lottano costantemente con le restrizioni nel superare il limite di 32 caratteri per i nomi degli eventi dei dispositivi analitici di UEFN.

Per i minigiochi casual, questi limiti sono gestibili. Ma per RPG persistenti complessi, shooter con live-ops o titoli multipiattaforma, affidarsi esclusivamente a una persistenza proprietaria e a circuito chiuso blocca il percorso di scalabilità.

The Architect's Alternative: database di stato esterni con horizOn

Per sviluppare un gioco scalabile che non sia limitato da bug dell'interfaccia utente specifici della piattaforma o dalle dimensioni dei dati proprietari, gli sviluppatori si stanno orientando verso architetture Backend esterne. Invece di memorizzare gli stati di gioco nelle mappe di memoria locali di Verse, il vostro progetto UEFN può comunicare con un database esterno utilizzando il modulo http_client in Verse.

Questo approccio offre il controllo totale sul ciclo di salvataggio dei player. Quando dovete cancellare i dati di persistenza dei player, non dovete cercare un pulsante mancante sulla console Epic o inviare un aggiornamento del codice. Potete semplicemente eseguire uno script amministrativo del database o fare clic su un singolo pulsante nel pannello di controllo del vostro Backend per cancellare, migrare o applicare patch alle tabelle dei player.

Sviluppare tutto questo autonomamente richiede la configurazione di load balancer, lo sharding del database e la gestione dei certificati SSL — facilmente 4-6 settimane di lavoro. Con horizOn, questi servizi Backend sono preconfigurati, permettendovi di rilasciare il vostro gioco invece di occuparvi dell'infrastruttura.

Indirizzando gli stati dei player tramite horizOn, il vostro codice Verse di diventa un semplice client che legge e scrive lo stato tramite puliti endpoint REST:

# Pseudocode showing HTTP-based state synchronization with [horizOn](https://horizon.pm)
sync_manager_device := class(creative_device):

    # Send player progress to [horizOn](https://horizon.pm) endpoint
    SavePlayerState(Player : player, SaveData : player_save_data) : void =
        # In a real environment, you construct a JSON payload and dispatch it
        # via the Verse http_client. This bypasses the 12KB local persistence limit.
        RequestURL := "https://api.horizon.pm/v1/players/{GetPlayerID(Player)}/state"
        Print("Dispatching persistent payload to [horizOn](https://horizon.pm) at: {RequestURL}")
        
        # This keeps the server-side payload lightweight (under 240 bytes) 
        # while securing long-term storage off the Fortnite engine.

Questo setup scollega completamente il vostro gameplay loop dai bug fisici del Backend della piattaforma. Se una patch interrompe la compatibilità dei salvataggi locali, potete attivare una migrazione mirata dello schema sul vostro database horizOn in tempo reale, con zero disservizi per il server di gioco live. Eviterete così il rischio di compromtere i server live per piccole modifiche strutturali.

Best Practices for Managing Game State Persistence

Sia che decidiate di utilizzare le mappe Verse native o di sfruttare un'architettura server esterna, mantenere un ciclo di vita della persistenza stabile è fondamentale per i giochi multiplayer. Attenetevi a questi principi per proteggere gli stati dei player:

  1. Implementare presto il versioning implicito: includete sempre un intero SchemaVersion nel layout iniziale dei dati di salvataggio. Anche se non prevedete di modificare lo schema, disporre della chiave di versione fin dal primo giorno previene la corruzione catastrofica dei dati in futuro.
  2. Applicare regole di validazione dello stato: quando leggete lo stato caricato, verificate l'intervallo di ogni attributo. Se la quantità di oro salvata di un player è negativa o supera il limite strutturale della mappa, resettate quella specifica proprietà per prevenire exploit nell'economia di gioco.
  3. Minimizzare la frequenza di salvataggio: scrivere sul cloud è dispendioso. Invece di aggiornare il database a ogni moneta raccolta, eseguite i salvataggi in batch. Avviate i salvataggi durante milestone chiave, come il completamento del match, il level-up del player o quando il player lascia la sessione.
  4. Creare struct di fallback pulite: non permettete mai che una lettura non riuscita impedisca a un player di entrare in gioco. Se la deserializzazione del payload di persistenza fallisce, passate istantaneamente a una struttura di stato predefinita.
  5. Disaccoppiare il codice di gameplay dalla logica di storage: mantenete le query di storage isolate in un persistence manager device dedicato. I dispositivi delle armi, della progressione e della UI dovrebbero interrogare questo gestore anziché effettuare chiamate dirette alla mappa dei dati.

Next Steps

Affidarsi alla console UI di Epic per gestire migrazioni di stato critiche è un design pattern rischioso. Quando l'opzione "Clear Player Data" non funziona, il versioning a runtime in Verse rappresenta la prima linea di difesa. Tuttavia, se il vostro gioco richiede salvataggi ad alta frequenza, telemetria complessa o un controllo amministrativo completo, migrare il database su un Backend dedicato è la soluzione definitiva.

Siete pronti a scalare il vostro Backend multiplayer? Provate horizOn gratuitamente o consultate la documentazione delle API.


Fonte: clear players data button in creative 1