Overview
The Wildlife Spawner device populates your map with Fortnite wildlife — boars, wolves, raptors, frogs — and exposes a rich Verse surface so those creatures become gameplay, not scenery. Reach for it when you want:
- A tameable companion a player can befriend and fight alongside (
Tame,TamedEvent). - A rideable mount the player teleports onto and rides (
Ride,RiddenEvent,Dismount). - An energy/stamina economy where feeding restores energy and sprinting drains it (
RestoreEnergy,ConsumeEnergy,SomethingIsEatenEvent). - A boss/horde encounter where you spawn waves and score eliminations (
Spawn,SpawnAt,EliminatedEvent,EliminatingEvent).
Everything below uses the device's real methods and events. The key idea: place the device in your level, expose it as an @editable field on a Verse creative_device, then call its methods inside OnBegin and from event handlers.
API Reference
wildlife_spawner_device
Used to customize the properties of NPCs spawned by this device. Changing properties will only affect newly spawned wildlife creatures.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
wildlife_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 this device spawns wildlife. Sends the agent wildlife that was spawned. |
EliminatedEvent |
EliminatedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when wildlife is eliminated. Source is the agent that eliminated the wildlife. If the wildlife was eliminated by a non-agent, or because the oldest wildlife was eliminated as Spawn function was called after spawn count was exce |
EliminatingEvent |
EliminatingEvent<public>:listenable(device_ai_interaction_result) |
Signaled when a wildlife eliminates an agent. Source is the wildlife that eliminated the agent. Target is the agent that was eliminated. |
TamedEvent |
TamedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when wildlife is tamed. Source is the agent that tamed the wildlife. Target is the wildlife that was tamed. |
UntamedEvent |
UntamedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when wildlife is untamed. Source is the agent that tamed the wildlife. Target is the wildlife that was untamed. |
ForceSpawnedEvent |
ForceSpawnedEvent<public>:listenable(agent) |
Signaled when wildlife is force-spawned and causes the oldest wildlife to be eliminated. Sends the agent wildlife that was spawned. |
DamagedEvent |
DamagedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when wildlife is damaged. Source is the agent that damaged the wildlife. If the wildlife was damaged by a non-agent then false is returned. Target is the wildlife that was damaged. |
SomethingIsEatenEvent |
SomethingIsEatenEvent<public>:listenable(agent) |
Signaled when wildlife eats a pickup such as a Shroom or Meat. Sends the wildlife that ate something. |
RiddenEvent |
RiddenEvent<public>:listenable(device_ai_interaction_result) |
Signaled when an agent rides wildlife. Source is the agent that started riding the wildlife. Target is the wildlife that was ridden. |
DismountedEvent |
DismountedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when an agent dismounts wildlife. Source is the agent that dismounted the wildlife. Target is the wildlife that was dismounted. |
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. |
Spawn |
Spawn<public>():void |
Spawns wildlife from this device. If spawn count is exceeded the oldest wildlife will be eliminated. |
Despawn |
Despawn<public>(Agent:agent):void |
Despawns wildlife. Agent is marked as the one who eliminated the wildlife. |
DestroySpawner |
DestroySpawner<public>(Agent:agent):void |
Destroys this device, marking Agent as the destroyer of the device. |
Tame |
Tame<public>(Agent:agent):void |
Tames wildlife, making them AI partners of Agent. |
Untame |
Untame<public>(Agent:agent):void |
Untames any tamed wildlife that belong to Agent. |
UntameAll |
UntameAll<public>():void |
Untames all wildlife. |
Ride |
Ride<public>(Agent:agent):void |
Teleports Agent to the nearest wildlife, then Agent mounts that wildlife. |
Dismount |
Dismount<public>(Agent:agent):void |
Dismounts Agent from wildlife. |
DismountAll |
DismountAll<public>():void |
Dismounts all agents from wildlife. |
RestoreEnergy |
RestoreEnergy<public>(Agent:agent):void |
Restores energy to wildlife belonging to Agent by Energy Restore Amount. |
RestoreEnergyForAll |
RestoreEnergyForAll<public>():void |
Restores energy to wildlife by Energy Restore Amount. |
ConsumeEnergy |
ConsumeEnergy<public>(Agent:agent):void |
Consumes energy from wildlife belonging to Agent by Energy Consume Amount. |
ConsumeEnergyForAll |
ConsumeEnergyForAll<public>():void |
Consumes energy from wildlife by Energy Consume Amount. |
GetSpawnLimit |
GetSpawnLimit<public>()<transacts>:int |
Returns the spawn limit of the device. |
GetAgents |
GetAgents<public>()<transacts>:[]agent |
Get all agents created by this device. |
SpawnAt |
SpawnAt<public>(Position:(/Verse.org/SpatialMath:)vector3, ?Rotation:?(/Verse.org/SpatialMath:)rotation |
Spawn a creature 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 |
Walkthrough
Let's build a Creature Ranch: when the game starts we spawn a creature, and a player who steps on a trigger tames the nearest creature into their AI partner. Once tamed, a button mounts them onto it. We also feed energy back when the creature eats, and announce eliminations on a HUD message device.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/Patchwork }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporal }
# A localized-text helper: `message` params need a localized value, not a raw string.
ranch_msg<localizes>(S:string):message = "{S}"
creature_ranch := class(creative_device):
# Drag your placed devices onto these fields in the Details panel.
@editable Wildlife : wildlife_spawner_device = wildlife_spawner_device{}
@editable TameTrigger : trigger_device = trigger_device{}
@editable RideButton : button_device = button_device{}
@editable Hud : hud_message_device = hud_message_device{}
OnBegin<override>()<suspends>:void =
# React to the device's lifecycle events.
Wildlife.SpawnedEvent.Subscribe(OnCreatureSpawned)
Wildlife.TamedEvent.Subscribe(OnCreatureTamed)
Wildlife.RiddenEvent.Subscribe(OnCreatureRidden)
Wildlife.SomethingIsEatenEvent.Subscribe(OnCreatureAte)
Wildlife.EliminatedEvent.Subscribe(OnCreatureEliminated)
# Player interactions drive the taming / riding.
TameTrigger.TriggeredEvent.Subscribe(OnTameStep)
RideButton.InteractedWithEvent.Subscribe(OnRidePress)
# Kick off the encounter with one creature.
Wildlife.Enable()
Wildlife.Spawn()
Print("Ranch open — spawn limit is {Wildlife.GetSpawnLimit()}")
# SpawnedEvent hands us the wildlife agent directly (listenable(agent)).
OnCreatureSpawned(Creature : agent):void =
Print("A creature spawned. Total alive: {Wildlife.GetAgents().Length}")
# Player steps on the plate -> tame the nearest creature for that player.
OnTameStep(Agent : ?agent):void =
if (Player := Agent?):
Wildlife.Tame(Player)
# TamedEvent gives a device_ai_interaction_result: Source = tamer, Target = creature.
OnCreatureTamed(Result : device_ai_interaction_result):void =
if (Tamer := Result.Source?):
Hud.Show(Tamer, ?Text := ranch_msg("You tamed a creature! Press the button to ride."))
# Button press -> teleport the player onto their nearest creature and mount it.
OnRidePress(Agent : agent):void =
Wildlife.Ride(Agent)
# RiddenEvent: Source = rider, Target = the wildlife being ridden.
OnCreatureRidden(Result : device_ai_interaction_result):void =
if (Rider := Result.Source?):
# Top off the mount's energy so the player can sprint right away.
Wildlife.RestoreEnergy(Rider)
# Wildlife ate a Shroom/Meat pickup -> reward the whole herd with energy.
OnCreatureAte(Creature : agent):void =
Wildlife.RestoreEnergyForAll()
# EliminatedEvent is a device_ai_interaction_result. Source may be the eliminator.
OnCreatureEliminated(Result : device_ai_interaction_result):void =
if (Killer := Result.Source?):
Hud.Show(Killer, ?Text := ranch_msg("Creature down! Respawning the herd."))
# Repopulate so the ranch is never empty.
Wildlife.Spawn()
Line-by-line:
- The
@editablefields are how Verse reaches the placed devices. A bareWildlife.Spawn()on an undeclared device fails with Unknown identifier — the field declaration is mandatory. - In
OnBeginweSubscribeeach event to a method defined at class scope.OnBeginis where subscriptions live. Wildlife.Enable()thenWildlife.Spawn()activates the device and pushes out the first creature.GetSpawnLimit()returns the configured cap as anint.SpawnedEventandSomethingIsEatenEventarelistenable(agent)— their handlers receive a plainagent(the creature). No unwrap needed.TriggeredEventislistenable(?agent), soOnTameSteptakes?agentand we unwrap withif (Player := Agent?):before passing it toTame.TamedEvent,RiddenEvent, andEliminatedEventarelistenable(device_ai_interaction_result). The result carriesSource(the acting agent) andTarget(the creature). Both are optional — unwrapResult.Source?before use.Hud.Showtakes amessage; we build one with theranch_msg<localizes>helper. There is noStringToMessage.
Common patterns
Spawn at an exact position with SpawnAt (suspends)
SpawnAt is <suspends> because the engine streams in the NPC asset before returning it. It returns ?agent — false if the spawn cap is hit. Call it from a suspending context.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
using { /UnrealEngine.com/Temporal }
ambush_spawner := class(creative_device):
@editable Wildlife : wildlife_spawner_device = wildlife_spawner_device{}
@editable StartButton : button_device = button_device{}
OnBegin<override>()<suspends>:void =
StartButton.InteractedWithEvent.Subscribe(OnStart)
OnStart(Agent : agent):void =
# Launch the suspending spawn work without blocking the handler.
spawn{ SpawnAmbush() }
SpawnAmbush()<suspends>:void =
# Drop three creatures in a line ahead of the device.
for (I := 0..2):
SpawnPos := vector3{ X := 500.0 * Float(I), Y := 0.0, Z := 100.0 }
if (Beast := Wildlife.SpawnAt(SpawnPos)?):
Print("Spawned creature #{I} at the ambush point")
Sleep(0.5)
A stamina drain: ConsumeEnergy while riding, RestoreEnergy on feed
Use ConsumeEnergyForAll/RestoreEnergy to build a stamina loop. Here a "sprint" trigger drains the herd; an eaten pickup restores the rider's mount.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/Patchwork }
using { /Verse.org/Simulation }
stamina_loop := class(creative_device):
@editable Wildlife : wildlife_spawner_device = wildlife_spawner_device{}
@editable SprintPad : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
SprintPad.TriggeredEvent.Subscribe(OnSprint)
Wildlife.SomethingIsEatenEvent.Subscribe(OnAte)
Wildlife.DismountedEvent.Subscribe(OnDismount)
# Stepping on the sprint pad burns energy across every creature.
OnSprint(Agent : ?agent):void =
Wildlife.ConsumeEnergyForAll()
# Eating refills energy for the whole herd.
OnAte(Creature : agent):void =
Wildlife.RestoreEnergyForAll()
# On dismount, untame so the creature returns to the wild.
OnDismount(Result : device_ai_interaction_result):void =
if (Rider := Result.Source?):
Wildlife.Untame(Rider)
Cleanup: despawn, untame all, and tear down the spawner
When a round ends, dismiss every creature cleanly. DismountAll and UntameAll take no args; DestroySpawner and Despawn need an agent to credit.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
round_cleanup := class(creative_device):
@editable Wildlife : wildlife_spawner_device = wildlife_spawner_device{}
@editable EndTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
EndTrigger.TriggeredEvent.Subscribe(OnRoundEnd)
OnRoundEnd(Agent : ?agent):void =
# Get everyone off mounts and break all tame bonds first.
Wildlife.DismountAll()
Wildlife.UntameAll()
# Despawn each creature, crediting the agent who ended the round.
if (Ender := Agent?):
for (Beast : Wildlife.GetAgents()):
Wildlife.Despawn(Ender)
# Finally disable so no new creatures appear.
Wildlife.Disable()
Gotchas
SpawnAtis<suspends>and returns?agent. You cannot call it from a plain(...)voidhandler directly — wrap it inspawn{ ... }or call it from another<suspends>function. Always unwrap the result withif (Beast := Wildlife.SpawnAt(Pos)?):— it returnsfalsewhen the spawn limit is reached.device_ai_interaction_result.Sourceand.Targetare optional. Events likeTamedEvent,RiddenEvent,EliminatedEvent, andDamagedEventhand you a result whoseSource/Targetmust be unwrapped (if (A := Result.Source?):). A non-agent eliminator (e.g. a fall) leavesSourceempty.SpawnedEventvsTamedEventpayloads differ.SpawnedEvent/ForceSpawnedEvent/SomethingIsEatenEventarelistenable(agent)— handler signature is(Creature : agent). The interaction events arelistenable(device_ai_interaction_result). Mixing the two signatures causes a type error onSubscribe.TriggeredEventgives?agent, notagent. When piping a trigger intoTame/Ride, unwrap first.RideandTamerequire a non-optionalagent.messageparams need localized text.Hud.Show(..., ?Text := ...)won't accept a raw string. Declare a<localizes>helper likeranch_msg<localizes>(S:string):message = "{S}"and passranch_msg("...").- Property changes only affect new spawns. The device docs note that changing its configured properties affects newly spawned creatures only — already-spawned wildlife keep their original settings. Re-
Spawnto apply updated config. - int↔float is not automatic.
SpawnAtneeds avector3of floats; convert ints withFloat(I)as shown in the ambush example. Tame/RestoreEnergyare per-agent. They act on wildlife belonging to the passed agent. Use the...ForAll/UntameAll/DismountAllvariants when you mean the whole herd.