Kembali ke Blog

Apakah weak_map Verse Melakukan Auto-Clean Saat Player Keluar di UEFN?

Diterbitkan pada 5 Juni 2026
Apakah weak_map Verse Melakukan Auto-Clean Saat Player Keluar di UEFN?

Ringkasnya

Artikel ini membahas miskonsepsi seputar manajemen memori `weak_map` di Verse untuk Unreal Editor for Fortnite (UEFN). Meskipun menggunakan weak reference, engine tidak melakukan auto-clean terhadap entry player saat mereka keluar dari game, sehingga berpotensi memicu runtime crash dan kebocoran state. Untuk mencegahnya, developer disarankan memisahkan data sesi transient dari cloud database dan membangun rutin cleanup manual secara eksplisit. Artikel ini juga menyarankan penggunaan horizOn SDK untuk mendelegasikan manajemen sesi dan data player ke cloud backend secara otomatis.

Jika Anda memercayai AI coding assistant Anda saat ia memberi tahu bahwa Verse secara otomatis menghapus data player dari weak_map pada milidetik yang sama ketika mereka disconnect dari island Fortnite Anda, Anda sedang bersiap menghadapi runtime crash yang parah. Klaim tersebut terdengar logis: karena ini adalah weak reference, engine seharusnya membersihkan key tersebut setelah object player terkena Garbage Collection. Namun di Unreal Editor for Fortnite (UEFN), realitasnya jauh lebih kompleks, dan kesalahpahaman tentang bagaimana memory manager Verse memproses player lifecycle akan menyebabkan silent state leak dan exception yang merusak game.

Ketika seorang player keluar, mereferensikan object mereka yang stale di dalam map dapat memicu ErrRuntime_WeakMapInvalidKey yang menakutkan atau mengakibatkan crash di seluruh island, sehingga mengharuskan Anda menerapkan UEFN server crash fix protocol yang ketat untuk menjaga server Anda tetap stabil. Untuk menghindari hal ini, developer harus mempelajari cara Verse mengelola memory secara internal dan cara menerapkan routine cleanup yang otoritatif.

Miskonsepsi: Saran Buatan AI vs. Realitas Verse

Banyak developer bertanya kepada AI assistant mereka tentang cara menangani data map player ketika mereka meninggalkan match. Salah satu saran umum yang dihasilkan AI adalah bahwa engine memperlakukan key player sebagai "weak reference" dan secara otomatis menghapus entry player dari map saat keluar. Hal ini sepenuhnya salah.

Meskipun weak_map(player, t) pada Verse menggunakan weak reference sebagai key di balik layar untuk mencegah hard reference cycle yang dapat memblokir Garbage Collector, ia tidak melakukan cleanup otomatis secara instan terhadap entry map itu sendiri. Entry tersebut—yang berisi slot key beserta data terkaitnya—tetap dialokasikan di dalam container map.

Jika code Anda mencoba mengakses, mengevaluasi, atau mengubah key tersebut setelah player keluar, runtime Verse akan mencoba mendereferensikan object player yang null atau tidak valid. Alih-alih gagal secara aman (fail gracefully), runtime akan memicu crash atau memunculkan uncatchable exception. Sistem mengharapkan Anda untuk menangani transisi lifecycle secara eksplisit daripada mengandalkan cleanup otomatis.

Mengapa Weak Map Tidak Melakukan Auto-Clean pada Entry Player

Untuk memahami mengapa hal ini terjadi, kita harus melihat tujuan penggunaan weak_map di UEFN. Tidak seperti lingkungan pemrograman standar di mana weak map berfungsi sebagai transient memory cache, Verse menggunakan weak_map(player, t) terutama sebagai gerbang untuk data player yang persisten.

Bertahan Lintas Sesi Permainan

Ketika Anda menggunakan weak_map(player, t) yang dideklarasikan pada lingkup module (module scope), engine akan menghubungkan nilai-nilainya ke dalam persistent cloud database milik Epic. Jika seorang player keluar dari match dan kembali tiga hari kemudian, engine akan mencocokkan player ID mereka dengan key map yang persisten untuk memulihkan progress mereka.

Jika engine secara otomatis menghapus entry player dari map begitu mereka keluar dari game, map tersebut akan kehilangan semua data persisten. Level, custom currency, dan item yang telah di-unlock akan di-reset menjadi nol setiap kali player disconnect atau mengalami network timeout. Oleh karena itu, database dirancang untuk menjaga entry ini tetap utuh justru karena data tersebut dimaksudkan untuk bertahan melewati pemutusan koneksi.

Scoped Lifetime dari Object Player

Ketika seorang player meninggalkan match, object active session mereka di dalam playspace akan dihancurkan. Referensi player fisik yang disimpan oleh code Verse Anda menjadi dead handle.

Karena key di dalam map sekarang mengarah ke object yang tidak valid dan tidak aktif, melakukan query pada map menggunakan referensi mati tersebut akan gagal. Engine tidak secara aktif memindai dan membersihkan dead key dari map secara real time. Sebaliknya, engine membiarkannya tidak aktif, itulah mengapa pengelolaan manual sangat wajib dilakukan untuk mencegah akumulasi stale reference.

Konsekuensi: Memory Leak, Stale Data, dan Server Crash

Kegagalan membersihkan entry player menyebabkan tiga masalah utama yang menurunkan performa game dan stabilitas server selama match yang berlangsung lama.

  • Stale Data Leakage: Jika seorang player keluar dan player lain bergabung, player baru tersebut mungkin mewarisi data sesi player lama jika engine menggunakan kembali slot player internal. Hal ini menyebabkan state bug, seperti player baru yang spawn dengan tas inventory penuh atau statistik match yang salah.
  • Memory Accumulation: Meskipun satu boolean atau integer membutuhkan ruang yang sangat kecil, menyimpan struktur kompleks hingga 50 player dalam lobby berkapasitas tinggi dapat meningkatkan penggunaan memory. Selama sesi server berdurasi 4 jam, akumulasi ini dapat menurunkan tick rate server.
  • Look-up Failures: Mencoba melakukan query pada status player yang tidak aktif atau memanggil fungsi pada referensi player yang sudah mati akan langsung memicu runtime crash.

Menabrak Batas Epic Cloud Save

UEFN memberlakukan batasan ketat pada data persisten. Anda dibatasi maksimal 4 persistent weak_map per island, dan ukuran record individu setiap player tidak boleh melebihi 256 KB data.

Jika Anda menggunakan weak_map persisten untuk menyimpan state sesi sementara, Anda membuang-buang ruang database yang berharga ini. Setiap update akan menulis ke database Epic, berisiko terkena penalti write-throttling atau melebihi batas 256 KB, yang akan memicu runtime error saat mencoba menulis lebih banyak data.

Tutorial Langkah demi Langkah: Mengelola State Sesi Player dengan Aman

Untuk mengelola state player tanpa risiko memory leak atau pembengkakan database, Anda harus memisahkan data sesi transient Anda dari data cloud persisten Anda. Data transient sebaiknya disimpan dalam map standar non-persisten, yang harus Anda bersihkan secara manual saat player disconnect.

Langkah 1: Tentukan Struct State Sesi Anda

Mulailah dengan mendefinisikan struct non-persistable yang berisi semua variabel yang dibutuhkan player Anda selama satu round atau match. Jangan tandai class atau struct ini sebagai <persistable>.

# Define the transient data structure for active gameplay tracking
player_session_state := struct:
    IsMoneyBagFull : logic = false
    CurrentGold : int = 0
    SpawnTime : float = 0.0

Langkah 2: Buat Manager Device

Buat sebuah creative device yang bertindak sebagai koordinator. Device ini akan menampung mutable, non-persistent map dari player yang aktif. Karena map standar di Verse bersifat immutable, kita deklarasikan variabel map tersebut sebagai var sehingga kita dapat menimpanya saat player bergabung atau keluar.

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

# Device handling player lifecycle events and session state mapping
state_manager_device := class(creative_device):

    # Non-persistent map for tracking active player sessions
    var SessionStates : [player]player_session_state = map{}

Langkah 3: Subscribe ke Playspace Event

Di dalam fungsi OnBegin, lakukan subscribe ke connection event milik playspace. Ini memastikan bahwa Anda menjalankan code inisialisasi saat player bergabung, dan code cleanup saat mereka keluar.

    OnBegin<override>()<suspends>:void=
        GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
        GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)
        
        # Initialize any players already in the session (useful for UEFN hot-reloading)
        for (Player : GetPlayspace().GetPlayers()):
            OnPlayerAdded(Player)

Langkah 4: Terapkan Logika Registrasi dan Cleanup

Ketika seorang player bergabung, isi map dengan default session state mereka. Ketika mereka keluar, Anda harus membersihkan entry mereka dari map. Karena Verse tidak menyediakan fungsi bawaan Map.Remove(), Anda harus merekonstruksi map tersebut dengan menyaring player yang keluar. Hal ini mencegah stale reference tertinggal di dalam memory.

    # Triggered when a player connects to the server
    OnPlayerAdded(Player: player):void=
        if (not SessionStates[Player]):
            InitialState := player_session_state{IsMoneyBagFull := false, CurrentGold := 0, SpawnTime := GetEngineTime()}
            if (set SessionStates[Player] = InitialState):
                Print("Initialized gameplay state for joining player.")

    # Triggered when a player disconnects or leaves the game
    OnPlayerRemoved(Player: player):void=
        Print("Player disconnected. Initiating map cleanup.")
        RemovePlayerSession(Player)

    # Purges the player's entry by reconstructing the map
    RemovePlayerSession(PlayerToRemove: player):void=
        var CleanedStates : [player]player_session_state = map{}
        for (ActivePlayer -> State : SessionStates):
            # Copy all players except the one who left
            if (ActivePlayer <> PlayerToRemove):
                if (set CleanedStates[ActivePlayer] = State):
                    # Entry successfully migrated to the cleaned map
        
        set SessionStates = CleanedStates
        Print("Successfully removed player session entry from memory.")

Dengan membangun kembali map saat penghapusan player, Anda sepenuhnya menghapus reference key tersebut. Garbage Collector kemudian dapat mereklaim resource player tanpa meninggalkan stale entry di dalam game loop Anda.

Jika Anda ingin melacak telemetry kustom selama transisi lifecycle ini, Anda juga harus memperhatikan batasan seperti 32-character analytics event name limit in Verse saat melaporkan durasi sesi atau statistik currency ke external backend.

Best Practice untuk Manajemen State Verse

Untuk memastikan server UEFN Anda tetap stabil dan berperforma tinggi, ikuti panduan berikut dalam mengelola data player:

  1. Differentiate Session vs. Persistent Data: Jangan pernah menyimpan variabel berumur pendek (seperti health match saat ini, round score, atau posisi sementara) di dalam weak_map yang persisten. Simpan transient state dalam map mutable standar yang dibungkus di dalam manager class.
  2. Verify Player Activity dengan IsActive: Sebelum mengambil atau memodifikasi data player di map mana pun, periksa apakah mereka masih ada di dalam playspace menggunakan query IsActive[]. Jika IsActive[] mengembalikan nilai false, batalkan pencarian dan picu event cleanup.
  3. Pantau Ukuran Data dengan FitsInPlayerMap: Saat menulis ke persistent weak_map, panggil FitsInPlayerMap() untuk memastikan pembaruan tidak akan melebihi batas 256 KB, guna mencegah runtime exception.
  4. Konsolidasikan Map Anda: Jangan membuat map terpisah untuk setiap variabel. Tentukan satu class yang berisi semua variabel player lalu map player tersebut ke class tersebut. Cara ini meminimalkan jumlah map Anda dan menghormati batas island yaitu maksimal empat persistent weak map.

Mendelegasikan Kompleksitas ke Cloud Backend yang Andal

Mengelola player session lifecycle, batasan database, dan logika cleanup manual di Verse dapat dengan cepat menjadi rumit. Jika Anda perlu membangun cross-session progression, inventory yang disinkronkan secara global, atau regional matchmaking, mengelola state ini secara manual membutuhkan pengaturan webhook, penskalaan database eksternal, dan penanganan sinkronisasi server-ke-server.

Dengan horizOn, tantangan backend ini ditangani secara otomatis. Dengan mengintegrasikan SDK horizOn ke server game Anda, Anda dapat mendelegasikan player session management ke cloud database khusus. Saat seorang player disconnect, horizOn memicu cleanup sesi otomatis, memperbarui database global, dan menyinkronkan data inventory di berbagai server instance tanpa menabrak batas memory Verse sebesar 256 KB atau berisiko mengalami runtime crash.

Siap untuk meningkatkan skala backend UEFN Anda? Coba horizOn secara gratis atau pelajari API docs kami.


Source: When using weak maps, does a player's entry in the map automatically get removed on them leaving the game?