Reference Devices compiles

Conjuring Shells: SpawnProp at Runtime

Placing props by hand is fine for scenery, but a collectible hunt needs shells that appear in fresh spots every round. Verse's `SpawnProp` lets your device conjure a `creative_prop` out of a `creative_prop_asset` at any position you choose while the game is running — and `Dispose` sweeps them away again. Coral the flamingo calls it beach magic; the compiler calls it a `tuple(?creative_prop, spawn_prop_result)`.

Updated Examples verified on the live UEFN compiler
Watch the Knotspawn_prop in ~90 seconds.

Welcome back to South Shores! So far you have wired up devices that were already sitting on the sand. Today Coral teaches you the trick every treasure hunt needs: making props appear out of thin air. SpawnProp takes a creative_prop_asset (the recipe for a prop) plus a transform (the where), and stamps a live creative_prop onto the island at runtime. When the round ends, Dispose clears them off again. No spawner device required — your Verse code is the spawner.

What you will build

A shell conjurer device for the Shell Hunt capstone: each round it shuffles a set of spawn-point markers, spawns N collectible shell props at the first N markers, waits out the round, then disposes every shell so the next round starts on a clean beach. This is exactly the "runtime-spawning the N collectible shells at shuffled spawn points" piece the South Shores capstone minigame is built around.

You will learn to:

  • Reference a prop asset with @editable ShellAsset : creative_prop_asset = DefaultCreativePropAsset
  • Call SpawnProp(Asset, Transform) and understand its return value: tuple(?creative_prop, spawn_prop_result)
  • Check spawn success by unwrapping element 0 with if (Shell := SpawnResult(0)?)
  • Track spawned props in a var array and Dispose() them at round end
  • Shuffle spawn points with Shuffle from /Verse.org/Random

Walkthrough

Step 1 — Set the stage in UEFN

  1. Drop a shell prop asset into your project (any small prop works — a conch from the Fortnite props gallery is perfect).
  2. Place a handful of small marker props along the beach where shells are allowed to appear (8-12 markers gives the shuffle room to breathe). You can hide the markers under the sand or make them invisible — we only read their transforms.
  3. Create a new Verse device with the code below, drag it into the level, then wire up the Details panel: the shell asset into ShellAsset, and every marker prop into the SpawnMarkers array.

Step 2 — The complete device

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

# Spawns a round of collectible shells at shuffled marker positions,
# then clears them away so the next round starts fresh.
shell_conjurer_device := class(creative_device):

    # The shell prop to spawn. Drag your shell asset into this
    # field in the UEFN Details panel.
    @editable
    ShellAsset : creative_prop_asset = DefaultCreativePropAsset

    # Marker props placed on the beach. Each marker's transform
    # is a possible spawn point for a shell.
    @editable
    SpawnMarkers : []creative_prop = array{}

    # How many shells each round should conjure.
    @editable
    ShellsPerRound : int = 5

    # How long a round lasts before the shells are cleared.
    @editable
    RoundSeconds : float = 20.0

    # Every shell spawned this round, so we can Dispose them later.
    var SpawnedShells : []creative_prop = array{}

    OnBegin<override>()<suspends>:void =
        loop:
            SpawnRound()
            Sleep(RoundSeconds)
            CleanupRound()
            Sleep(2.0)   # a short beat between rounds

    # Shuffle the markers and spawn a shell at the first ShellsPerRound.
    SpawnRound():void =
        Shuffled := Shuffle(SpawnMarkers)
        for (Index := 0..ShellsPerRound - 1, Marker := Shuffled[Index]):
            SpawnShellAt(Marker.GetTransform())

    # Spawn one shell and record it if the spawn succeeded.
    SpawnShellAt(SpawnTransform : transform):void =
        # SpawnProp returns tuple(?creative_prop, spawn_prop_result).
        SpawnResult := SpawnProp(ShellAsset, SpawnTransform)
        if (Shell := SpawnResult(0)?):
            # Element 0 held a real prop - the spawn worked.
            set SpawnedShells += array{Shell}
            Print("Shell conjured! {SpawnedShells.Length} on the beach.")
        else:
            # Element 0 was false - element 1 says why (see spawn_prop_result).
            Print("A shell refused to appear. Check the spawn_prop_result.")

    # Dispose every shell that is still on the island.
    CleanupRound():void =
        for (Shell : SpawnedShells, Shell.IsValid[]):
            Shell.Dispose()
        set SpawnedShells = array{}
        Print("Beach swept clean for the next round.")

Step 3 — How the spawn call works, line by line

Piece What it does
ShellAsset : creative_prop_asset = DefaultCreativePropAsset An @editable asset reference. DefaultCreativePropAsset is the safe placeholder default until you drag in a real asset.
Shuffle(SpawnMarkers) From /Verse.org/Random — returns a new array with the markers in random order, so every round uses different spawn points.
for (Index := 0..ShellsPerRound - 1, Marker := Shuffled[Index]) Iterates the first N shuffled markers. The failable index Shuffled[Index] quietly skips out-of-range values, so asking for 5 shells with only 3 markers spawns 3 — no crash.
SpawnProp(ShellAsset, SpawnTransform) The star of the show. Returns a tuple: element 0 is ?creative_prop (the spawned prop, or false on failure), element 1 is a spawn_prop_result enum explaining the outcome.
if (Shell := SpawnResult(0)?) The success check: unwrapping the option succeeds only when a prop was actually created. Inside the if, Shell is a real creative_prop.
Shell.IsValid[] Succeeds only if the prop has not already been disposed (a collected shell might already be gone).
Shell.Dispose() Destroys the prop and removes it from the island.

Why the result enum matters

spawn_prop_result tells you why a spawn failed: Ok, UnknownError, InvalidSpawnPoint (NaN/Inf coordinates), SpawnPointOutOfBounds (outside the island), InvalidAsset, or TooManyProps. That last one is the big one — the island rules currently allow 100 spawned props per script device and 200 total per island. A round-based cleanup with Dispose, like ours, is how you stay comfortably under that budget.

Common patterns

Pattern 1 — Scatter spawning with the Position + Rotation overload

SpawnProp has a second overload that takes a vector3 position and a rotation instead of a whole transform. Handy when you want random scatter around a point instead of exact marker positions:

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

scatter_spawner_device := class(creative_device):

    @editable
    ShellAsset : creative_prop_asset = DefaultCreativePropAsset

    var SpawnedShells : []creative_prop = array{}

    OnBegin<override>()<suspends>:void =
        # Scatter 3 shells around this device's own position.
        BasePosition := GetTransform().Translation
        for (Count := 0..2):
            SpawnScattered(BasePosition)

    # Spawn a shell near a base position with random offset,
    # using the Position + Rotation overload of SpawnProp.
    SpawnScattered(BasePosition : vector3):void =
        Offset := vector3{
            X := GetRandomFloat(-150.0, 150.0),
            Y := GetRandomFloat(-150.0, 150.0),
            Z := 0.0
        }
        SpawnResult := SpawnProp(ShellAsset, BasePosition + Offset, IdentityRotation())
        if (Shell := SpawnResult(0)?):
            set SpawnedShells += array{Shell}

Pattern 2 — Reading the result enum for diagnostics

When spawns fail mysteriously during testing, compare element 1 against the spawn_prop_result cases:

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

diagnostic_spawner_device := class(creative_device):

    @editable
    ShellAsset : creative_prop_asset = DefaultCreativePropAsset

    OnBegin<override>()<suspends>:void =
        SpawnWithDiagnostics(GetTransform())

    SpawnWithDiagnostics(SpawnTransform : transform):void =
        Result := SpawnProp(ShellAsset, SpawnTransform)
        if (Result(1) = spawn_prop_result.Ok):
            Print("Spawn OK.")
        else if (Result(1) = spawn_prop_result.TooManyProps):
            Print("Prop budget hit: 100 per script device, 200 per island.")
        else:
            Print("Spawn failed - check InvalidAsset / SpawnPointOutOfBounds.")

Where this goes next

This device is the beating heart of the Shell Hunt capstone at the end of South Shores. The capstone imports this exact spawning skill: each game round it calls the same shuffle-then-SpawnProp routine to place the collectible shells, listens for players collecting them, and reuses CleanupRound between rounds so the beach — and the island prop budget — stays clean. Nail the SpawnResult(0)? success check now, and the capstone's round loop will feel like a warm tide coming in.

Build your own lesson with spawn_prop

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →