Reference Devices compiles

guard_spawner_device: AI Guards for PvE and Objective Defense

Every stronghold needs defenders and every objective needs threats. The guard_spawner_device drops fully-behaved AI guards into your island — they patrol, detect intruders, chase, and fight. From Verse you can spawn them on demand, react to alerts and eliminations, hire them as allies, and even force them to attack a specific player.

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

Overview

The guard_spawner_device is your one-stop shop for AI combatants. Placed in the editor, it spawns guard-type NPCs that already know how to patrol an area (or follow an AI Patrol Path Node), fill a suspicion meter when they see a target, go Alert, chase, and attack. You configure their weapons, team, accuracy, and spawn count in the device's User Options; you drive the timing and reactions from Verse.

Reach for it when you need:

  • PvE enemies — waves of guards to fight through.
  • Objective defense — guards protecting a vault, terminal, or capture point that turn hostile when players approach.
  • Hireable allies — guards a player can recruit that leash to and protect them.
  • Scripted encounters — spawn a guard at an exact position, then force it to hunt a chosen player.

The key rule to remember: changing device properties only affects guards spawned afterward, and the device has a spawn limit. Verse lets you subscribe to a rich set of perception events (SuspiciousEvent, AlertedEvent, TargetLostEvent, UnawareEvent) plus combat events (DamagedEvent, EliminatedEvent, EliminatingEvent) and hiring events (HiredEvent, DismissedEvent), so you can react to the full guard lifecycle.

API Reference

guard_spawner_device

Used to spawn guards that can patrol and attack other agents. Changing properties will only affect newly spawned guards.

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

guard_spawner_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
SpawnedEvent SpawnedEvent<public>:listenable(agent) Signaled when a guard is spawned. Sends the agent guard who was spawned.
AlertedEvent AlertedEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard has identified an opponent. Source is the guard who is aware. Target is the agent who alerted the guard.
TargetLostEvent TargetLostEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard has lost track of a target. Source is the guard that lost track of a target. Target is the agent no longer targeted by the guard.
SuspiciousEvent SuspiciousEvent<public>:listenable(agent) Signaled when a guard becomes suspicious. Sends the agent guard who is suspicious.
UnawareEvent UnawareEvent<public>:listenable(agent) Signaled when a guard becomes unaware. Sends the agent guard who is unaware.
DamagedEvent DamagedEvent<public>:listenable(device_ai_interaction_result) Signaled when guard is damaged. Source is the agent that damaged the guard. If the guard was damaged by a non-agent then false is returned. Target is the guard that was damaged.
EliminatedEvent EliminatedEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard is eliminated. Source is the agent that eliminated the guard. If the guard was eliminated by a non-agent then Source is 'false'. Target is the guard that was eliminated.
EliminatingEvent EliminatingEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard eliminates an agent. Source is the guard that eliminated the agent. Target is the agent that was eliminated.
HiredEvent HiredEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard is hired by a player. Source is the agent who hired the guard. Target is the guard that was hired.
DismissedEvent DismissedEvent<public>:listenable(device_ai_interaction_result) Signaled when a guard is dismissed by a player. Source is the agent who dismissed the guard. Target is the guard that was dismissed.

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>():void Enables this device. Guards will start to spawn.
Disable Disable<public>():void Disables this device. Guards will despawn if Despawn Guards When Disabled is set.
Spawn Spawn<public>():void Tries to spawn a guard.
Spawn Spawn<public>(Instigator:agent):void Tries to spawn a guard. If Auto Hire When Spawned is set to Triggering Player the guard will be hired by Instigator.
Despawn Despawn<public>():void Despawns guards.
Despawn Despawn<public>(Instigator:agent):void Despawns guards. Instigator will be considered as the eliminator of those guards.
Hire Hire<public>(Instigator:agent):void Hires guards to Instigator's team.
DismissAllHiredGuards DismissAllHiredGuards<public>():void Dismisses all hired guards.
DismissAgentHiredGuards DismissAgentHiredGuards<public>(Instigator:agent):void Dismisses all hired guards that were recruited by Instigator.
ForceAttackTarget ForceAttackTarget<public>(Target:agent, ?ForgetTime:float Forces guards to attack Target, bypassing perception checks. 'ForgetTime' ranges from 0.0 to 600.0 (in seconds, default is 600.0), it is the time after which the target will be ignored if not found. 'ForgetDistance' ranges from 0.0 to 100
SetGuardsHireable SetGuardsHireable<public>():void Allows guards to be hired.
SetGuardsNotHireable SetGuardsNotHireable<public>():void Prevents guards from being hired.
GetSpawnLimit GetSpawnLimit<public>()<transacts>:int Returns the spawn limit of the device.
GetAgents GetAgents<public>()<transacts>:[]agent Get all agents created by this device.
SetName SetName<public>(InText:message):void Sets the name of the guard in the hire the guard conversation and elimination feed.
GetName GetName<public>():string Gets the name of the guard in the hire the guard conversation and elimination feed.
SpawnAt SpawnAt<public>(Position:(/Verse.org/SpatialMath:)vector3, ?Rotation:?(/Verse.org/SpatialMath:)rotation Spawn a guard at the given position. When Rotation is not provided, it will default to the Devices rotation. Returns the agent spawned or false if the device has reached its maximum spawn count. This function is <suspends>` because it tak

Walkthrough

Let's build a vault-defense encounter. Two guards defend a vault. A pressure plate (a trigger_device) tells the spawner when the raiding player steps into the room, so we spawn the defenders and force them to attack that player. We track eliminations, and when the last defender falls we open the vault door (a barrier_device we Disable to let the player through).

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

vault_defense := class(creative_device):

    # The spawner that produces our defending guards.
    @editable
    GuardSpawner : guard_spawner_device = guard_spawner_device{}

    # Pressure plate the raider steps on to trigger the fight.
    @editable
    IntrusionPlate : trigger_device = trigger_device{}

    # The vault door barrier; we disable it once all guards are down.
    @editable
    VaultDoor : barrier_device = barrier_device{}

    # How many guards are still alive.
    var GuardsRemaining : int = 0

    # Localized helper so we can name our guards (message, not string).
    NameText<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Give the guards a name shown in the elimination feed.
        GuardSpawner.SetName(NameText("Vault Sentinel"))

        # React to the whole guard lifecycle.
        GuardSpawner.SpawnedEvent.Subscribe(OnGuardSpawned)
        GuardSpawner.AlertedEvent.Subscribe(OnGuardAlerted)
        GuardSpawner.EliminatedEvent.Subscribe(OnGuardEliminated)

        # The plate starts the encounter.
        IntrusionPlate.TriggeredEvent.Subscribe(OnPlateStepped)

    # Player stepped on the plate: wake the spawner and force the fight.
    OnPlateStepped(Agent : ?agent) : void =
        if (Raider := Agent?):
            # Enable the device so it will accept spawns.
            GuardSpawner.Enable()
            # Spawn up to the device's configured count.
            SpawnLimit := GuardSpawner.GetSpawnLimit()
            var Count : int = 0
            loop:
                if (Count >= SpawnLimit):
                    break
                GuardSpawner.Spawn()
                set Count = Count + 1
            # Everything the device has produced should hunt the raider.
            for (Guard : GuardSpawner.GetAgents()):
                GuardSpawner.ForceAttackTarget(Raider, ?ForgetTime := 600.0)

    # Count each guard as it appears.
    OnGuardSpawned(Guard : agent) : void =
        set GuardsRemaining = GuardsRemaining + 1

    # A guard spotted someone — nothing extra needed, but log-worthy hook.
    OnGuardAlerted(Result : device_ai_interaction_result) : void =
        # Source is the guard, Target is who alerted them (optional agent).
        if (Target := Result.Target?):
            # We could highlight the raider here; left as a hook.
            GuardSpawner.ForceAttackTarget(Target, ?ForgetTime := 600.0)

    # A guard died. When the last one falls, open the vault.
    OnGuardEliminated(Result : device_ai_interaction_result) : void =
        set GuardsRemaining = GuardsRemaining - 1
        if (GuardsRemaining <= 0):
            # Reward: drop the barrier so the player can loot the vault.
            VaultDoor.Disable()

Line by line:

  • The @editable fields let you drop the real placed devices into the panel. Without declaring the spawner as a field you could not call any of its methods.
  • NameText<localizes> builds a messageSetName requires localized text, so we can never pass a raw string.
  • In OnBegin we subscribe our handler methods to the device's events. SpawnedEvent hands us a raw agent; the interaction events hand us a device_ai_interaction_result with Source and Target.
  • OnPlateStepped unwraps the optional agent with if (Raider := Agent?). We Enable() the spawner, then call Spawn() in a loop up to GetSpawnLimit() so we never exceed the device's cap.
  • GetAgents() returns every agent this device created; we loop and ForceAttackTarget each toward the raider, bypassing perception so the fight starts immediately. ?ForgetTime := 600.0 keeps them locked on for the full 10 minutes.
  • OnGuardEliminated decrements the counter and, when it reaches zero, Disable()s the barrier — the vault opens.

Common patterns

Hireable ally guards

Let a player recruit a guard from a button, then hire the spawner's guards onto their team. React to the HiredEvent.

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

ally_recruiter := class(creative_device):

    @editable
    AllySpawner : guard_spawner_device = guard_spawner_device{}

    @editable
    HireButton : button_device = button_device{}

    OnBegin<override>()<suspends> : void =
        # Allow these guards to be recruited.
        AllySpawner.SetGuardsHireable()
        AllySpawner.HiredEvent.Subscribe(OnHired)
        HireButton.InteractedWithEvent.Subscribe(OnHirePressed)

    OnHirePressed(Agent : agent) : void =
        # Hire whatever this spawner has produced onto the player's team.
        AllySpawner.Hire(Agent)

    OnHired(Result : device_ai_interaction_result) : void =
        # Source is the player who hired; Target is the recruited guard.
        if (Player := Result.Source?):
            # Guard now leashes to and protects the player.
            AllySpawner.SetGuardsNotHireable()

Suspicion / detection feedback

Use the perception events to build a stealth loop — light up an alarm when a guard gets suspicious, clear it when they lose the target.

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

alarm_system := class(creative_device):

    @editable
    PatrolSpawner : guard_spawner_device = guard_spawner_device{}

    # A light or FX driver enabled while guards are alerted.
    @editable
    AlarmLight : device_ability_kit = device_ability_kit{}

    OnBegin<override>()<suspends> : void =
        PatrolSpawner.Enable()
        PatrolSpawner.SuspiciousEvent.Subscribe(OnSuspicious)
        PatrolSpawner.TargetLostEvent.Subscribe(OnTargetLost)
        PatrolSpawner.UnawareEvent.Subscribe(OnUnaware)

    OnSuspicious(Guard : agent) : void =
        # A guard sees something. Escalate by forcing a spawn of reinforcements.
        PatrolSpawner.Spawn()

    OnTargetLost(Result : device_ai_interaction_result) : void =
        # Guard lost track — dismiss any player-hired guards to reset the scene.
        PatrolSpawner.DismissAllHiredGuards()

    OnUnaware(Guard : agent) : void =
        # Guard fully calmed down; no action needed here.
        PatrolSpawner.Disable()

Scripted spawn at an exact spot

SpawnAt is <suspends> and returns the spawned agent (or fails). Use it for cinematic ambushes at precise coordinates.

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

ambush_trap := class(creative_device):

    @editable
    AmbushSpawner : guard_spawner_device = guard_spawner_device{}

    @editable
    Tripwire : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        AmbushSpawner.Enable()
        Tripwire.TriggeredEvent.Subscribe(OnTripped)

    OnTripped(Agent : ?agent) : void =
        if (Victim := Agent?):
            spawn { SpringAmbush(Victim) }

    SpringAmbush(Victim : agent)<suspends> : void =
        # Spawn a guard right beside the victim's ambush point.
        SpawnPos : vector3 = vector3{ X := 500.0, Y := 0.0, Z := 100.0 }
        if (Guard := AmbushSpawner.SpawnAt(SpawnPos)):
            # Lock the fresh guard onto the victim immediately.
            AmbushSpawner.ForceAttackTarget(Victim, ?ForgetTime := 120.0)

Gotchas

  • Properties are apply-on-spawn. Weapon, team, accuracy, and name changes only affect guards spawned after you set them. SetName before you Spawn, not after.
  • SetName needs a message, not a string. There is no StringToMessage. Declare a NameText<localizes>(S:string):message = "{S}" helper and pass NameText("...").
  • Respect the spawn limit. Spawn() silently does nothing once the device hits GetSpawnLimit(). Loop against GetSpawnLimit() (as in the walkthrough) or the device just stops producing guards. If you need a fresh batch, the device also offers Reset to reset the spawn count.
  • Interaction-event fields are optional. In a device_ai_interaction_result, Source and Target are ?agent — always unwrap with if (X := Result.Source?). When a guard is damaged/eliminated by non-agent damage (fall, environment), Source is false.
  • SpawnAt is <suspends> and can fail. Call it from inside a spawn{} block or another <suspends> context, and wrap it in if (Guard := ...SpawnAt(Pos)): because it fails when the device is at max count.
  • Enable/Disable and despawn interact. Disable() only despawns guards if the device's Despawn Guards When Disabled option is set — otherwise existing guards stay. Use Despawn() explicitly if you want them gone.
  • Patrol paths are set in the editor, not Verse. Match the spawner's Spawn on Patrol Path Group to the AI Patrol Path Node's Patrol Path Group number so fresh guards start patrolling.

Device Settings & Options

The guard_spawner_device User Options panel in the UEFN editor — every setting you can tune.

Guard Spawner Device settings and options panel in the UEFN editor — Guard Type, Spawn Count, Spawn Through Walls, Enabled at Game Start, Item List
Guard Spawner Device — User Options in the UEFN editor: Guard Type, Spawn Count, Spawn Through Walls, Enabled at Game Start, Item List
⚙️ Settings on this device (5)

Setting names read from the panel above — may be partial; the screenshots are the source of truth.

Guard Type
Spawn Count
Spawn Through Walls
Enabled at Game Start
Item List

Guides & scripts that use guard_spawner_device

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

Build your own lesson with guard_spawner_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 →