Reference Devices compiles

physics_object_base_device: Spawning Destructible Boulders & Trees on Cue

Need a boulder that drops when a player crosses a trigger, or a forest of physics trees you can clear with a single call? The physics_object_base_device is the shared parent of UEFN's physics prop spawners — and it gives you four clean controls from Verse: Enable, Disable, SpawnObject, and DestroyAllSpawnedObjects.

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

Overview

The physics_object_base_device is the abstract base class behind UEFN's physics-driven prop spawners — things like the Physics Boulder and physics-tree props. You never place a physics_object_base_device directly; instead you place one of its concrete children (for example physics_boulder_device), but every one of them inherits the same core control surface defined here.

That shared surface solves a very common game problem: I want a heavy physics object to appear, do its physics thing, and then be cleaned up — all under script control. Picture an obstacle course where stepping on a pressure plate drops a boulder, or a defense round where you spawn a wave of destructible trees and then wipe them all when the round ends.

Reach for this device's API when you want to:

  • Spawn the physics prop on demand with SpawnObject().
  • Turn the spawner on/off with Enable() / Disable() so it can't fire while disabled.
  • Clean up every prop it created in one shot with DestroyAllSpawnedObjects().

Because it descends from prop_spawner_base_device, the concrete devices (like the boulder) also add their own events on top — but the four methods below are the reliable, always-available foundation.

API Reference

physics_object_base_device

Base class for various physics-based gameplay elements (e.g. boulders/trees).

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from prop_spawner_base_device.

physics_object_base_device<public> := class<abstract><epic_internal>(prop_spawner_base_device):

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
SpawnObject SpawnObject<public>():void Spawns the prop associated with this device.
DestroyAllSpawnedObjects DestroyAllSpawnedObjects<public>():void Destroys all props spawned from this device.

Walkthrough

Let's build a classic boulder trap. A player steps on a trigger_device; we spawn a boulder from a physics_boulder_device (a concrete physics_object_base_device). When the round-end button_device is pressed, we destroy every boulder we spawned and disable the spawner so no more can drop.

We declare each placed device as an @editable field so Verse can actually reach it, then wire the events in OnBegin.

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

# A boulder-trap manager. Drag the matching devices onto these slots in UEFN.
boulder_trap_device := class(creative_device):

    # The physics boulder spawner. physics_boulder_device IS a physics_object_base_device.
    @editable
    BoulderSpawner : physics_boulder_device = physics_boulder_device{}

    # Player steps here to drop a boulder.
    @editable
    TrapTrigger : trigger_device = trigger_device{}

    # Pressed at round end to clean everything up.
    @editable
    ResetButton : button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        # Make sure the spawner is active when the round starts.
        BoulderSpawner.Enable()

        # Wire the trigger and the reset button to our handler methods.
        TrapTrigger.TriggeredEvent.Subscribe(OnTrapStepped)
        ResetButton.InteractedWithEvent.Subscribe(OnResetPressed)

    # Runs each time a player steps on the trap trigger.
    OnTrapStepped(Agent : ?agent):void =
        # Drop a fresh boulder from the spawner.
        BoulderSpawner.SpawnObject()

    # Runs when a player interacts with the reset button.
    OnResetPressed(Agent : agent):void =
        # Wipe every boulder this spawner created...
        BoulderSpawner.DestroyAllSpawnedObjects()
        # ...and stop it from spawning any more until we re-enable it.
        BoulderSpawner.Disable()

Line by line:

  • @editable BoulderSpawner : physics_boulder_device — the concrete boulder spawner. Because it inherits from physics_object_base_device, calling .Enable(), .SpawnObject(), and .DestroyAllSpawnedObjects() on it is valid. A bare physics_object_base_device field would be illegal — it's <abstract> and can't be instantiated or placed.
  • OnBegin<override>()<suspends>:void — the device's entry point. We call BoulderSpawner.Enable() first so the spawner is guaranteed live.
  • TrapTrigger.TriggeredEvent.Subscribe(OnTrapStepped) — subscribes our method to the trigger's event. The trigger's TriggeredEvent is listenable(?agent), so the handler takes (Agent : ?agent).
  • OnTrapStepped — every time someone steps on the plate, SpawnObject() makes a new boulder appear and roll/fall with real physics.
  • OnResetPressedDestroyAllSpawnedObjects() removes the whole pile of boulders, then Disable() shuts the spawner off so the trap is safe until you Enable() it again.

Common patterns

1. Spawn a wave on a timer, then clear it

Use a timer_device so a boulder drops every time the timer completes, and a separate signal to flush them all.

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

wave_spawner_device := class(creative_device):

    @editable
    Spawner : physics_boulder_device = physics_boulder_device{}

    @editable
    WaveTimer : timer_device = timer_device{}

    @editable
    ClearButton : button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        Spawner.Enable()
        # Each time the timer finishes, spawn another physics object.
        WaveTimer.SuccessEvent.Subscribe(OnTimerDone)
        ClearButton.InteractedWithEvent.Subscribe(OnClear)
        WaveTimer.Start()

    OnTimerDone(Agent : ?agent):void =
        Spawner.SpawnObject()

    OnClear(Agent : agent):void =
        Spawner.DestroyAllSpawnedObjects()

2. Gate spawning behind game state with Enable / Disable

Keep the spawner disabled until a round actually starts, so stray triggers can't pre-fire it.

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

round_gate_device := class(creative_device):

    @editable
    Spawner : physics_boulder_device = physics_boulder_device{}

    @editable
    StartButton : button_device = button_device{}

    @editable
    EndButton : button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        # Start the round with the spawner OFF.
        Spawner.Disable()
        StartButton.InteractedWithEvent.Subscribe(OnRoundStart)
        EndButton.InteractedWithEvent.Subscribe(OnRoundEnd)

    OnRoundStart(Agent : agent):void =
        Spawner.Enable()
        Spawner.SpawnObject()

    OnRoundEnd(Agent : agent):void =
        Spawner.Disable()
        Spawner.DestroyAllSpawnedObjects()

3. Burst-spawn several objects at once

SpawnObject() spawns one prop per call — loop it for a burst, then offer a one-call cleanup.

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

burst_spawner_device := class(creative_device):

    @editable
    Spawner : physics_boulder_device = physics_boulder_device{}

    @editable
    BurstTrigger : trigger_device = trigger_device{}

    @editable
    Count : int = 5

    OnBegin<override>()<suspends>:void =
        Spawner.Enable()
        BurstTrigger.TriggeredEvent.Subscribe(OnBurst)

    OnBurst(Agent : ?agent):void =
        # Drop `Count` physics objects in a single burst.
        for (I := 0..Count - 1):
            Spawner.SpawnObject()

Gotchas

  • The base class is abstract — you place a child. physics_object_base_device is <abstract>, so you cannot place it or write physics_object_base_device{}. Declare your @editable field as a concrete subclass such as physics_boulder_device and drop that device in UEFN; it inherits all four methods.
  • No events live on the base class. The base surface is methods only — Enable, Disable, SpawnObject, DestroyAllSpawnedObjects. Events like BalancedBoulderSpawnedEvent belong to the concrete physics_boulder_device, not to physics_object_base_device. Don't try to Subscribe to an event on the base type.
  • SpawnObject() does nothing while disabled. If you've called Disable() (or never enabled the device), spawns may not occur. Always Enable() before you expect spawns, and remember DestroyAllSpawnedObjects() only removes props this device spawned.
  • Reach the device through an @editable field. A bare physics_boulder_device{}.SpawnObject() won't work — you need a field referencing the placed device. Calling a method on a default-constructed physics_boulder_device{} with no real placement behind it does nothing in the world.
  • Unwrap ?agent from trigger events. A trigger_device.TriggeredEvent handler receives (Agent : ?agent). If you need the actual player, unwrap with if (A := Agent?): before using it; button InteractedWithEvent instead hands you a plain agent.
  • DestroyAllSpawnedObjects() is a clean-up, not a disable. It removes existing props but the spawner stays enabled and will happily spawn again — pair it with Disable() if you want spawning to actually stop.

Build your own lesson with physics_object_base_device

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 →