Reference Scene Graph compiles

component & light_component: Building Your Island from Scene Graph Blocks

It's a bright cel-shaded morning on the cove, and the lantern hanging off the pirate ship's mast needs to glow when the sun dips. Scene Graph lets you build that lantern out of re-usable components — a transform to place it, a light to make it shine — instead of dragging pre-built devices. This is the source-of-truth guide to the component base class and its friends transform_component and light_component.

Updated Examples verified on the live UEFN compiler

Overview

Scene Graph is Verse's unified structure that connects every object on your island. Instead of placing finished devices, you assemble entities out of components — small, re-usable building blocks of data and logic. A component is the abstract base class every one of these blocks inherits from.

Two components you'll reach for constantly on any sunny dock scene:

  • transform_component — stores where an entity sits, how it's rotated, and how big it is. Nearly every visible entity needs one; a light_component depends on it to know where to shine.
  • light_component — the abstract base for lights (directional_light_component for sunlight, spot_light_component for a lantern cone, sphere_light_component for a glowing buoy, etc.). It's enableable, so you can flip it on and off.

Reach for these when you want a custom, self-contained object — a swinging lantern, a torch on the clifftop, a glowing treasure chest — that you can turn into a prefab and reuse across the island. Because components run in both edit and play mode, the classic Verse-device pattern is to place a creative_device, hold @editable references to your Scene Graph entities, and in OnBegin walk their components with GetComponents() / GetComponent[] to drive them.

API Reference

component

Base class for authoring logic and data in the SceneGraph. Using components you can author re-usable building blocks of logic and data which can then be added to entities in the scene. Components are a very low level building block which can be used in many ways. For example: * Exposing engine level concepts like mesh or sound * Adding gameplay capabilities like damage or interaction * Storing an

Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).

component<native><public> := class<abstract><unique><castable><final_super_base>:

transform_component

Stores the transforms for an entity, which are used to position the entity.

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

transform_component<native><public> := class<final><final_super>(component):

light_component

Base class for light components in the SceneGraph. Dependencies: * transform_component on the entity positions the light. Examples of components implementing light_component: * directional_light_component * capsule_light_component * sphere_light_component * rect_light_component * spot_light_component

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

light_component<native><public> := class<abstract><final_super><epic_internal>(component, enableable):

Walkthrough

The moment: A pirate-ship lantern hangs over the cove. When a player steps on the deck trigger, we find the lantern entity, grab its light_component, enable it, and nudge its transform_component up a hair so it swings into place — all from a Verse device.

The key idea: you can't call a bare Entity.Method() on a placed thing. You declare @editable fields on a creative_device, then in OnBegin you query the entity's components with the real Scene Graph API (GetComponents(), GetComponent[]).

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
using { /Verse.org }
using { /Verse.org/SceneGraph }
using { /Verse.org/SceneGraph/CollisionProfiles }

# Device that lights the pirate-ship lantern when a player steps on the deck plate.
lantern_lighter_device := class(creative_device):

    # The deck trigger the player steps on.
    @editable
    DeckPlate : trigger_device = trigger_device{}

    # The lantern ENTITY placed in the Scene Graph. Assign it in the Details panel.
    @editable
    LanternEntity : entity = entity{}

    OnBegin<override>()<suspends>:void =
        # Subscribe our handler to the deck plate.
        DeckPlate.TriggeredEvent.Subscribe(OnDeckStepped)

    # Runs every time an agent steps on the deck plate.
    OnDeckStepped(Agent : ?agent):void =
        # Turn the lantern's light on.
        LightTheLantern()

    LightTheLantern():void =
        # Find the light_component on the lantern entity and enable it.
        if (Light := LanternEntity.GetComponent[light_component]):
            Light.Enable()

        # Nudge the lantern up 20cm so it swings into its lit position.
        # Get/SetLocalTransform are extension methods on the ENTITY - they
        # read and write its transform_component's data under the hood.
        Current := LanternEntity.GetLocalTransform()
        Raised := transform:
            Translation := Current.Translation + vector3{ Forward := 0.0, Left := 0.0, Up := 20.0 }
            Rotation := Current.Rotation
            Scale := Current.Scale
        LanternEntity.SetLocalTransform(Raised)

Line by line:

  • The using lines pull in Scene Graph and its collision-profile helpers so entity, component, light_component, and transform_component resolve.
  • DeckPlate and LanternEntity are @editable fields — the only way to reference placed things. LanternEntity is a Scene Graph entity, not a device.
  • OnBegin subscribes OnDeckStepped to the plate's TriggeredEvent. Subscription always happens here.
  • OnDeckStepped(Agent : ?agent) is the handler. A listenable(?agent) event hands you an optional agent; we don't need the agent here so we just kick off the lantern logic.
  • GetComponent[light_component] is a failable lookup ([]), so it lives inside an if. If the lantern really has a light, Light.Enable() (from the enableable interface light_component implements) switches it on.
  • GetLocalTransform() / SetLocalTransform() are extension methods on the entity — they read and write the data stored in its transform_component under the hood (the component itself exposes that data as its LocalTransform field). We build a new transform raised 20cm on Up and write it back.

Common patterns

Pattern 1 — Enumerate every component on an entity with GetComponents(). Handy when you're wiring a prefab and want to confirm the pieces are there.

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

# Counts the components on the treasure-chest entity when a button is pressed.
chest_inspector_device := class(creative_device):

    @editable
    InspectButton : button_device = button_device{}

    @editable
    ChestEntity : entity = entity{}

    OnBegin<override>()<suspends>:void =
        InspectButton.InteractedWithEvent.Subscribe(OnInspect)

    OnInspect(Agent : agent):void =
        # GetComponents() returns []component — every direct component on the entity.
        Components := ChestEntity.GetComponents()
        Print("Chest has {Components.Length} components")

Pattern 2 — Walk child entities with GetEntities() and light each one. A row of clifftop torches, each a child entity of a parent "TorchLine", all switched on at once.

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

# Lights every torch child of the TorchLine entity when the round starts.
torch_line_device := class(creative_device):

    @editable
    TorchLine : entity = entity{}

    OnBegin<override>()<suspends>:void =
        # GetEntities() returns the DIRECT child entities of TorchLine.
        for (Torch : TorchLine.GetEntities()):
            if (Light := Torch.GetComponent[light_component]):
                Light.Enable()

Pattern 3 — Slide an entity along the dock by rewriting its local transform. GetLocalTransform()/SetLocalTransform() on the entity read and rewrite the data its transform_component stores, repositioning a floating buoy.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
using { /Verse.org }
using { /Verse.org/SceneGraph }
using { /Verse.org/SceneGraph/CollisionProfiles }

# Nudges a buoy entity 100cm forward when a trigger fires.
buoy_pusher_device := class(creative_device):

    @editable
    PushTrigger : trigger_device = trigger_device{}

    @editable
    BuoyEntity : entity = entity{}

    OnBegin<override>()<suspends>:void =
        PushTrigger.TriggeredEvent.Subscribe(OnPush)

    OnPush(Agent : ?agent):void =
        Old := BuoyEntity.GetLocalTransform()
        New := transform:
            Translation := Old.Translation + vector3{ Forward := 100.0, Left := 0.0, Up := 0.0 }
            Rotation := Old.Rotation
            Scale := Old.Scale
        BuoyEntity.SetLocalTransform(New)

Gotchas

  • component, light_component are abstract. You never construct a bare component{}. On placed entities you query for the concrete one you need with GetComponent[light_component] (which resolves to a directional_light_component, spot_light_component, etc. underneath).
  • GetComponent[...] is failable — always in an if or with or. Writing Entity.GetComponent[light_component].Enable() at statement level won't compile; wrap it: if (L := Entity.GetComponent[light_component]) { L.Enable() }.
  • light_component needs a transform_component. A light with no transform on its entity has nowhere to shine from. If your lantern goes dark, confirm the entity actually has a transform component.
  • Entities are NOT devices. You can't call device methods (Enable, Show) on an entity. You act on its components. And you still need a creative_device with @editable fields to hold references to them.
  • Components run in edit AND play mode. Logic you put directly in a custom component fires the moment you launch the session. If you want play-only behavior, drive it from a creative_device's OnBegin, as every example above does.
  • vector3 fields are Forward, Left, Up — not X/Y/Z. Scene Graph's /Verse.org/SpatialMath vector uses named axes: vector3{ Forward := 100.0, Left := 0.0, Up := 20.0 }.
  • int and float don't auto-convert. Transform translations are float vectors — write 20.0, never 20.
  • Don't pass raw strings where a message is required. If a UI call wants a message, declare MyText<localizes>(S:string):message = "{S}" and pass MyText("...") — there is no StringToMessage.

Guides & scripts that use component

Step-by-step tutorials that put this object to work.

Build your own lesson with component

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 →