Overview
The video_player_device displays curated videos on in-game screens or as a picture-in-picture (PIP) overlay on a player's HUD. Think of a lobby cinema, a tutorial screen that explains the objective, a jumbotron that replays a moment, or a countdown video that plays for everyone at round start.
Reach for it whenever you want video (not just audio or text) to react to gameplay: a player enters a trigger and the trailer starts, a boss dies and a victory clip fills the screen, or one device needs to take control of every screen on the island so an important announcement can't be missed.
In Verse the device gives you fine control over when and for whom video happens. You can Enable/Disable it, push it EnterFullScreen for a single agent, shrink or grow the PIP, Restart or Seek the stream, force a TakeControl/ReleaseControl priority override, and react to the StreamStartedEvent when a player becomes the controlling viewer.
API Reference
video_player_device
Used to display curated videos onto in-game screens or player HUDs.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
video_player_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
StreamStartedEvent |
StreamStartedEvent<public>:listenable(agent) |
Signaled when this device becomes the controlling streaming device for the agent. |
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. |
EnableCollision |
EnableCollision<public>():void |
Enables collision checks on this device. |
DisableCollision |
DisableCollision<public>():void |
Disables collision checks on this device. |
EnterFullScreen |
EnterFullScreen<public>(Agent:agent):void |
Transitions to fullscreen for Agent. |
ExitFullScreen |
ExitFullScreen<public>(Agent:agent):void |
Transitions to fullscreen for Agent. |
HidePIP |
HidePIP<public>(Agent:agent):void |
Hides the picture-in-picture video from Agent. |
MakePIPDefaultSize |
MakePIPDefaultSize<public>(Agent:agent):void |
Transitions the picture-in-picture video to the default size for Agent. |
MakePIPFullScreen |
MakePIPFullScreen<public>(Agent:agent):void |
Transitions the picture-in-picture video to full screen for Agent. |
EndForAll |
EndForAll<public>():void |
Turns off all streaming devices of this type on the island. |
Restart |
Restart<public>():void |
Restart the stream from the beginning. |
Seek |
Seek<public>():void |
Seeks to the Triggered Seek Time. Caution: The stream will pause while the video buffers when seeking. |
TakeControl |
TakeControl<public>():void |
Stops the currently playing stream and starts the custom stream with the audio only playing from this device. Stream Priority will not work until control is released. |
ReleaseControl |
ReleaseControl<public>():void |
If any streaming device has forced control of the stream, this will release it and play the highest priority stream in line. |
Walkthrough
Let's build a lobby theater. We place a video_player_device (the screen) and a trigger_device (a pressure plate at the theater entrance). When a player steps on the plate, we enable the screen, restart the clip from the top, and push it fullscreen for that player. We also subscribe to StreamStartedEvent so we know when the device has actually become the controlling stream for an agent.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
log_theater := class(log_channel){}
lobby_theater_device := class(creative_device):
Logger : log = log{Channel := log_theater}
# The screen that plays the curated video.
@editable
Screen : video_player_device = video_player_device{}
# The pressure plate at the theater entrance.
@editable
EntryPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
# React when a player steps on the plate.
EntryPlate.TriggeredEvent.Subscribe(OnPlayerEntered)
# React when the screen becomes the controlling stream for someone.
Screen.StreamStartedEvent.Subscribe(OnStreamStarted)
# Make sure the screen starts off until a player arrives.
Screen.Disable()
# TriggeredEvent hands us an ?agent — unwrap it before use.
OnPlayerEntered(Agent : ?agent):void =
if (Player := Agent?):
Screen.Enable() # turn the screen on
Screen.Restart() # play from the very beginning
Screen.EnterFullScreen(Player) # fill this player's view
Logger.Print("Theater started for a player")
OnStreamStarted(Player : agent):void =
Logger.Print("Stream is now controlling for an agent")
Line by line:
log_theater := class(log_channel){}andLogger : log = log{Channel := log_theater}give us a named log channel so ourPrintcalls show up tagged in the output.@editable Screen : video_player_deviceand@editable EntryPlate : trigger_deviceare the fields that let us reference the placed devices. Without declaring them as editable fields, callingScreen.Enable()would fail with 'Unknown identifier'. Drag each placed device into these slots in the Details panel.- In
OnBegin, weSubscribethe plate'sTriggeredEventto ourOnPlayerEnteredmethod and the screen'sStreamStartedEventtoOnStreamStarted. Event handlers are plain methods at class scope. Screen.Disable()keeps the screen dark until someone arrives.OnPlayerEntered(Agent : ?agent)— the trigger's event is alistenable(?agent), so the handler receives an optional agent.if (Player := Agent?):unwraps it; everything inside only runs when a real player is present.Screen.Enable()powers the device,Screen.Restart()rewinds the clip, andScreen.EnterFullScreen(Player)transitions that specific player's view to fullscreen.OnStreamStartedfires when the device becomes the controlling streaming device for an agent — handy for confirming playback actually began.
Common patterns
Picture-in-picture mini-screen, then promote to fullscreen
Show the video as a small PIP corner overlay first, and only blow it up to fullscreen on a second cue (e.g. a button press).
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
pip_promoter_device := class(creative_device):
@editable
Screen : video_player_device = video_player_device{}
@editable
PromoteButton : button_device = button_device{}
OnBegin<override>()<suspends>:void =
PromoteButton.InteractedWithEvent.Subscribe(OnPromote)
OnPromote(Agent : agent):void =
Screen.Enable()
Screen.MakePIPDefaultSize(Agent) # show small PIP overlay for this agent
Screen.MakePIPFullScreen(Agent) # then grow it to fill the HUD
A priority takeover for an emergency broadcast
One announcement screen forces control of every stream on the island, then releases it when the message is done.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
broadcast_device := class(creative_device):
@editable
AnnounceScreen : video_player_device = video_player_device{}
# Plate that starts the emergency broadcast.
@editable
StartPlate : trigger_device = trigger_device{}
# Plate that ends it and returns to normal programming.
@editable
EndPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
StartPlate.TriggeredEvent.Subscribe(OnStart)
EndPlate.TriggeredEvent.Subscribe(OnEnd)
OnStart(Agent : ?agent):void =
AnnounceScreen.Enable()
AnnounceScreen.TakeControl() # forces this stream over all others, audio from here
OnEnd(Agent : ?agent):void =
AnnounceScreen.ReleaseControl() # hand control back to highest-priority stream
Seek to a highlight and clean up all screens
Jump to a configured Triggered Seek Time, or shut every screen down at round end.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
highlight_device := class(creative_device):
@editable
Screen : video_player_device = video_player_device{}
@editable
SeekButton : button_device = button_device{}
@editable
RoundEndPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
SeekButton.InteractedWithEvent.Subscribe(OnSeek)
RoundEndPlate.TriggeredEvent.Subscribe(OnRoundEnd)
OnSeek(Agent : agent):void =
Screen.Enable()
Screen.Seek() # jumps to the device's configured Triggered Seek Time
OnRoundEnd(Agent : ?agent):void =
Screen.EndForAll() # turns off ALL video_player_devices on the island
Gotchas
- You must declare the device as an
@editablefield. A barevideo_player_device{}.Enable()won't work — Verse needs a field bound to a placed device in the Details panel. Forgetting to assign the device in-editor leaves it empty and methods do nothing. - Per-agent vs. island-wide methods.
EnterFullScreen,ExitFullScreen,HidePIP,MakePIPDefaultSize, andMakePIPFullScreenall take anagentand only affect that player's HUD.Enable,Disable,Restart,Seek,TakeControl,ReleaseControl, andEndForAllaffect the device/stream globally. Don't expectEnterFullScreen(P)to change anyone else's view. EndForAllis a nuke. It turns off everyvideo_player_deviceof this type on the island, not just this one. Use it for round resets, not to stop a single screen — useDisable()for that.TakeControlblocks Stream Priority. While a device holds control, Stream Priority settings are ignored until you callReleaseControl(). Always pair them, or other screens stay stuck.Seekpauses to buffer. Seeking causes the stream to pause while it buffers to the Triggered Seek Time, so a momentary stall is expected — don't treat it as a bug.- Unwrap optional agents. Trigger
TriggeredEventislistenable(?agent), so the handler gets?agent. Always doif (Player := Agent?):before passing it to a per-agent method. ButtonInteractedWithEventalready hands a non-optionalagent, so no unwrap is needed there. StreamStartedEventislistenable(agent)(non-optional) — the handler receives a plainagentyou can use directly.