Overview
A Post Process Volume placed in the level affects every player who walks through it, but it can't easily target one player, respond to game events, or animate smoothly in and out at runtime. The post_process_device solves all three problems.
Place the device in your UEFN level, configure its visual settings in the Details panel (color grading, bloom intensity, vignette strength, blend time, etc.), then drive it entirely from Verse:
- Per-player effects —
BlendIn(Agent)/BlendOut(Agent)/Enable(Agent)/Disable(Agent)target exactly one player. - Global effects —
BlendInForAll()/BlendOutForAll()/Enable()/Disable()/ResetForAll()hit every player simultaneously. - Completion events —
BlendingInCompleteEventandBlendingOutCompleteEventfire when the transition finishes, letting you chain logic (unlock a door, spawn enemies, play a sound).
Reach for post_process_device whenever you need a scripted, per-player, or event-driven visual effect that a static volume can't provide.
API Reference
post_process_device
Used to apply Post Process Effects to players through the creative device rather than a Post Process Volume.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
post_process_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
BlendingInCompleteEvent |
BlendingInCompleteEvent<public>:listenable(?agent) |
Signaled when a blend in event has finished. Sends the agent that used this device. |
BlendingOutCompleteEvent |
BlendingOutCompleteEvent<public>:listenable(?agent) |
Signaled when a blend out event has finished. Sends the agent that used this device. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>(Agent:agent):void |
Enables this device only for the instigating Agent. |
Enable |
Enable<public>():void |
Enables this device for all players. |
Disable |
Disable<public>(Agent:agent):void |
Disables this device only for the instigating Agent. |
Disable |
Disable<public>():void |
Disables this device for all players. |
BlendIn |
BlendIn<public>(Agent:agent):void |
Starts blending in the post process effect to the set strength only for the instigating Agent. |
BlendInForAll |
BlendInForAll<public>():void |
Starts blending in the post process effect to the set strength for all players. |
BlendOut |
BlendOut<public>(Agent:agent):void |
Starts blending out the post process effect to 0 strength only for the instigating Agent. |
BlendOutForAll |
BlendOutForAll<public>():void |
Starts blending out the post process effect to 0 strength for all players. |
ResetForAll |
ResetForAll<public>():void |
Resets to the starting strength, ending any ongoing blending for all players. |
Walkthrough
Scenario: The Poison Zone
A player steps on a pressure plate to enter a poison zone. The screen immediately starts blending to a sickly green tint (configured on the device). When the blend finishes, a message is logged and the effect holds. When the player leaves the zone (steps on an exit plate), the effect blends back out. If the round ends, all effects are reset for every player.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
using { /Verse.org/Simulation }
# Attach this Verse device to the scene.
# Wire up PoisonPlate, ExitPlate, and PoisonEffect in the Details panel.
poison_zone_manager := class(creative_device):
# The pressure plate that starts the poison effect.
@editable
PoisonPlate : trigger_device = trigger_device{}
# The pressure plate that ends the poison effect.
@editable
ExitPlate : trigger_device = trigger_device{}
# The post_process_device configured with a green-tint / vignette look.
@editable
PoisonEffect : post_process_device = post_process_device{}
# Called when the blend-in transition finishes for a player.
OnBlendInDone(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
Print("Poison effect fully active for agent.")
# You could apply damage-over-time logic here.
# Called when the blend-out transition finishes for a player.
OnBlendOutDone(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
Print("Poison effect cleared for agent.")
# Player stepped into the poison zone.
OnEnterPoison(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Enable the device for this player so it can affect them,
# then start the smooth blend-in transition.
PoisonEffect.Enable(A)
PoisonEffect.BlendIn(A)
# Player stepped out of the poison zone.
OnExitPoison(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Blend back out to zero strength for this player.
PoisonEffect.BlendOut(A)
OnBegin<override>()<suspends> : void =
# Subscribe to the pressure plates.
PoisonPlate.TriggeredEvent.Subscribe(OnEnterPoison)
ExitPlate.TriggeredEvent.Subscribe(OnExitPoison)
# Subscribe to blend completion events so we can chain logic.
PoisonEffect.BlendingInCompleteEvent.Subscribe(OnBlendInDone)
PoisonEffect.BlendingOutCompleteEvent.Subscribe(OnBlendOutDone)
Line-by-line explanation
| Lines | What's happening |
|---|---|
@editable PoisonPlate |
Exposes the trigger reference to the UEFN Details panel so you can wire it up without hardcoding. |
@editable PoisonEffect |
Same for the post_process_device — configure its visual look in the Details panel. |
OnEnterPoison |
Unwraps the ?agent the trigger sends, calls Enable(A) so the device is active for that player, then BlendIn(A) to start the animated transition. |
OnExitPoison |
Calls BlendOut(A) — the device animates back to 0 strength using the blend time set in the Details panel. |
BlendingInCompleteEvent.Subscribe |
Fires when the blend-in animation finishes — perfect for triggering follow-up logic like DoT ticks. |
BlendingOutCompleteEvent.Subscribe |
Fires when the blend-out finishes — you could call Disable(A) here to fully deactivate the device for that player. |
Common patterns
Pattern 1 — Global dramatic effect (boss spawn)
When the boss spawns, slam a red-tinted effect onto every player at once, then blend it out after a short delay.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
boss_spawn_fx := class(creative_device):
# A post_process_device set to a deep red vignette look.
@editable
BossEffect : post_process_device = post_process_device{}
# A trigger_device wired to the boss spawner's "On Spawn" output.
@editable
BossSpawnTrigger : trigger_device = trigger_device{}
OnBossSpawned(MaybeAgent : ?agent) : void =
# Blend the red effect in for ALL players simultaneously.
BossEffect.BlendInForAll()
# After 5 seconds, blend it back out for everyone.
spawn { FadeOutAfterDelay() }
FadeOutAfterDelay()<suspends> : void =
Sleep(5.0)
BossEffect.BlendOutForAll()
OnBegin<override>()<suspends> : void =
BossSpawnTrigger.TriggeredEvent.Subscribe(OnBossSpawned)
Pattern 2 — Instant enable/disable (no blend) for a specific player
Some effects (e.g. a "spectator mode" desaturation) should snap on and off instantly. Use Enable / Disable directly — they skip the blend animation.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
spectator_fx_controller := class(creative_device):
# Desaturation post-process device.
@editable
SpectatorEffect : post_process_device = post_process_device{}
# Triggered when a player is eliminated and enters spectator mode.
@editable
EliminatedTrigger : trigger_device = trigger_device{}
# Triggered when the spectator rejoins (e.g. respawn).
@editable
RespawnTrigger : trigger_device = trigger_device{}
OnEliminated(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Snap the desaturation effect on instantly — no blend.
SpectatorEffect.Enable(A)
OnRespawned(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Snap it off instantly.
SpectatorEffect.Disable(A)
OnBegin<override>()<suspends> : void =
EliminatedTrigger.TriggeredEvent.Subscribe(OnEliminated)
RespawnTrigger.TriggeredEvent.Subscribe(OnRespawned)
Pattern 3 — Round reset with ResetForAll
At the end of a round, cleanly reset every post-process effect to its starting strength for all players, cancelling any in-progress blends.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
round_reset_controller := class(creative_device):
# Any post_process_device active during the round.
@editable
RoundEffect : post_process_device = post_process_device{}
# A trigger wired to the Game Manager's "Round End" output.
@editable
RoundEndTrigger : trigger_device = trigger_device{}
OnRoundEnd(MaybeAgent : ?agent) : void =
# ResetForAll cancels any ongoing blend and restores the
# device to the starting strength configured in the Details panel.
RoundEffect.ResetForAll()
OnBegin<override>()<suspends> : void =
RoundEndTrigger.TriggeredEvent.Subscribe(OnRoundEnd)
Gotchas
1. Enable ≠ BlendIn — they are separate steps
Enable(Agent) activates the device for a player (making it eligible to affect them) but does not start the blend animation. Call BlendIn(Agent) after Enable(Agent) if you want the animated transition. Calling BlendIn on a disabled device may have no visible effect.
2. Always unwrap ?agent before use
Both BlendingInCompleteEvent and BlendingOutCompleteEvent (and trigger TriggeredEvent) deliver ?agent — an optional agent. You must unwrap it with if (A := MaybeAgent?): before passing it to per-player methods. Passing the raw ?agent to BlendIn(Agent:agent) is a compile error.
3. BlendOut targets zero, not Disable
BlendOut(Agent) animates the effect strength down to 0 — the device remains enabled. If you want to fully deactivate it (so it has zero CPU cost), call Disable(Agent) after BlendingOutCompleteEvent fires.
4. Blend time is set in the Details panel, not in Verse
There is no SetBlendTime() API. The blend duration is a property you configure on the placed device in UEFN. If you need different blend speeds for different situations, place multiple post_process_device instances with different blend times and reference them as separate @editable fields.
5. ResetForAll cancels in-progress blends
Calling ResetForAll() mid-blend snaps the effect back to its configured starting strength immediately for all players. Don't call it unless you intend to interrupt ongoing transitions — use BlendOutForAll() if you want a graceful exit.
6. No using lines in your file? You'll get "Unknown identifier"
Your Verse file must include using { /Fortnite.com/Devices } (and any other required modules) at the top. Without it, post_process_device, trigger_device, and other device types are unresolved symbols at compile time.