Back to the feed
Featured Tutorials 2026-06-21

Verse Language Get Started in Unreal Editor for Fortnite

Verse Language: Getting Started in UEFN

The Verse scripting language is Epic's statically-typed, concurrency-native language purpose-built for UEFN, giving you deterministic failure handling, speculative execution via transactions, and deep integration with Fortnite's device ecosystem. If you're moving from Blueprint or an external scripting layer, understanding how Verse's module system and editor tooling wire together is the difference between productive iteration and fighting the build pipeline.

What Changed

The documentation consolidates the end-to-end workflow for authoring Verse inside UEFN into a single canonical tutorial path. Key specifics covered:

  • Project-level Verse directory: Verse source files live under <ProjectName>/Content/Verse/ and are auto-discovered by the Verse Language Server; you do not manually register files with a build system.
  • using directives and module scoping: Every .verse file belongs to a module derived from its directory path. You reference platform APIs via using { /Fortnite.com/Devices }, using { /UnrealEngine.com/Temporary/Diagnostics }, etc.
  • Editor integration points: The UEFN toolbar exposes Verse → Build Verse Code (incremental) and errors surface in the Verse Diagnostics panel, not the Output Log. The language server provides hover-documentation and go-to-definition within the built-in editor.
  • creative_device as the entry point: All world-interactive Verse logic must subclass creative_device. The runtime calls OnBegin at device spawn and OnEnd at teardown; there is no free-standing main.
  • Playtest loop: Push-to-playtest triggers a full Verse compile; local syntax errors block the push, giving you a tight compile→test cycle without leaving the editor.

What You Can Build

1. A Self-Contained Round Timer with HUD Integration

Before this tooling stabilized, wiring a countdown to a HUD device required Blueprint intermediaries. Now you wire it entirely in Verse:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

round_timer_device := class(creative_device):
    @editable
    HUD : hud_message_device = hud_message_device{}

    @editable
    RoundDurationSeconds : float = 60.0

    OnBegin<override>()<suspends> : void =
        var Remaining : float = RoundDurationSeconds
        loop:
            if (Remaining <= 0.0):
                HUD.ShowMessage("Time's up!")
                break
            HUD.ShowMessage("Time: {Remaining}")
            Sleep(1.0)
            set Remaining -= 1.0

The <suspends> effect on OnBegin lets you use Sleep without blocking the game thread — this is the concurrency model Verse enforces at the type level.

2. Transactional Inventory Check (Speculative Execution)

Verse's option type and failure-context semantics let you safely attempt an operation and roll back without try/catch noise:

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }

GateOnItem<epic_internal>(Agent : agent, RequiredItem : item_definition) : logic =
    if:
        Character := Agent.GetFortCharacter[]
        # GetItemCount[] fails if the agent has none — failure propagates cleanly
        Count := Character.GetInventoryItemCount[RequiredItem]
        Count >= 1
    then:
        true
    else:
        false

Because [] denotes a failable call, the entire if block speculates; no item means clean failure, no exception, no nil dereference.

3. Multi-Device Orchestration via Event Subscriptions

The Awaitable pattern lets you coordinate multiple devices without a polling loop:

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

wave_manager_device := class(creative_device):
    @editable
    SpawnerA : creature_spawner_device = creature_spawner_device{}
    @editable
    SpawnerB : creature_spawner_device = creature_spawner_device{}
    @editable
    EndTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        SpawnerA.Enable()
        # Block until the trigger fires — no polling, no timer hack
        EndTrigger.TriggeredEvent.Await()
        SpawnerA.Disable()
        SpawnerB.Enable()

TriggeredEvent.Await() suspends only this coroutine; the rest of the simulation keeps running. This replaces multi-Blueprint event graphs with a linear, readable flow.

References

Linked docs

Related topics