Voice channels in Fortnite are divided into two categories:
Party Chat is for talking to players in your party while in Fortnite, the Epic Games Launcher, or the Epic Games app (including mobile).
Game Chat is for talking to players in the same island instance.
Game Chat uses a class called voice_channel which is a group of players who can hear one another on an island. Using Verse, you can create custom voice channels to separate players for gameplay purposes such as team-based chat, silencing eliminated players, or roles that can move between channels.
Verse voice channels aren't tied to player location. Everyone in the channel hears everyone else at the same volume, from no particular direction (attenuation), no matter how far apart they are (spatialization). That means Verse voice channels can’t be used for proximity chat.
In this document, you’ll create a device that holds two channels: Red and Blue. Players on Red can hear each other and players on Blue can hear each other — but crosstalk isn’t possible.
You’ll use five buttons to trigger the following functionality:
Assign the player to Red.
Assign the player to Blue.
Remove the player from all channels.
Mute and unmute a player without changing their channel assignment.
Toggle channels on or off without changing player assignment.
You’ll also add testing quality-of-life functionality, such as on-screen messages that confirm when a button is working.
When building your own island, you can use any Verse event as a trigger.
An island can use Verse voice channels or Attenuate Voice (proximity chat), but not both at the same time. If both are present in an island, Verse voice channels will take precedence.
Party Chat cannot be overridden by Game Chat. Even if players are on different Game Chat channels, a party can always talk to one another.
Create a Voice Channel Device
To create a voice channel device, follow these steps:
In Unreal Editor for Fortnite (UEFN), create a new island or open an existing one.
If the Verse Explorer isn’t open, navigate to the main menu and click Verse > Verse Explorer.
In the Verse Explorer, right-click your island and select Create Verse File.
In the Create Verse Script window, in the Device Name field, enter
voice_channel_test_device.Click Create Empty.
In the Verse Explorer, double-click your new verse file and paste the following lines inside:
Verseusing { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/Diagnostics } using { /Verse.org/AgentGroup } using { /Verse.org/Chat } using { /Verse.org/SceneGraph } using { /Verse.org/Simulation } test_voice_member_info := class(has_voice_member_info) {}
In the next section, you’ll create the four building blocks of a voice channel: a member info class, agent groups, voice channels, and registration. Then, you’ll build functionality for the five buttons and HUD elements that let you know when the buttons are working.
To skip to a complete version of the code, see Detect Speaking.
Create a Member Info Class
A member_info class holds a player’s voice settings, including CanBroadcast which decides whether the player can speak. You’ll use this later on when creating the functionality for the Toggle Mute Button.
To create a member_info class, paste the following code above voice_channel_test_device:
test_voice_member_info := class(has_voice_member_info) {}Create Agent Groups
Players must be part of an agent_group to appear on a channel’s roster. When changing a channel’s roster, you add or remove players in the agent_group, not in the voice_channel itself. Since this example has two channels, you’ll need two agent groups; RedGroup and BlueGroup.
To create the groups, paste the following code inside voice_channel_test_device, directly below the class line:
RedGroup:agent_group(test_voice_member_info) = agent_group(test_voice_member_info){}
BlueGroup:agent_group(test_voice_member_info) = agent_group(test_voice_member_info){}A player can belong to several channels at once. Their voice is sent to every channel where they can broadcast, however, they can only hear one channel at a time — the channel they joined last.
Create and Register Channels
Registration activates a channel. Each voice_channel must be registered at the start of a game and also after every round. To be registered, each channel needs a Name.
To create names, paste the following code between test_voice_member_info and voice_channel_test_device:
RedName<localizes>:message = "Red"
BlueName<localizes>:message = "Blue"To handle registration, paste the following code inside voice_channel_test_device, below BlueGroup:
var RedChannel:?voice_channel(test_voice_member_info) = false
var BlueChannel:?voice_channel(test_voice_member_info) = false
OnBegin<override>()<suspends>:void=
set RedChannel = Register(RedName, RedGroup)
set BlueChannel = Register(BlueName, BlueGroup)
Register(ChannelName:message, Roster:agent_group(test_voice_member_info)):?voice_channel(test_voice_member_info)=
You might have noticed that this code block contains print strings. In this case, the code prints whether the channels are successfully registered and flags when it fails. Since a channel can only hold up to 80 players, it prints a failstate if there are over 80.
However, print strings are only visible in development environments, not on published islands. In the next section, you’ll use Report and ReportSpeaking to get visual confirmation that a button worked during a playtest on a private island.
Set Up the HUD and Buttons
You’ll use button_device for your buttons, and hud_message_device to display on-screen messages. Since HUD message devices require the message type, you’ll use StatusMessage to convert plain text into a message. Then, you’ll use Report and ReportSpeaking to display that text on screen. You’ll use seven variables to control these devices:
| Name | Function |
|---|---|
JoinRedButton | Assign the player to Red. |
JoinBlueButton | Assign the player to Blue. |
LeaveButton | Remove the player from all channels. |
ToggleMuteButton | Mute and unmute a player without changing their channel assignment. |
ToggleChannelsButton | Toggle channels on or off without changing player assignment. |
ActionHUD | Displays a message when a player presses a button. |
SpeakingHUD | Displays when a player starts or stops speaking. |
To create this functionality, follow these steps:
Paste the following code below
BlueName:VerseStatusMessage<localizes>(Text:string):message = "{Text}"Paste the following code inside
voice_channel_test_device, directly below the class line:Verse@editable JoinRedButton:button_device = button_device{} @editable JoinBlueButton:button_device = button_device{} @editable LeaveButton:button_device = button_device{} @editablePaste the following code inside
voice_channel_test_device, betweenOnBeginandRegister:VerseReport(Text:string):void= Print(Text) ActionHUD.SetText(StatusMessage(Text)) ActionHUD.Show() ReportSpeaking(Text:string):void= Print(Text) SpeakingHUD.SetText(StatusMessage(Text)) SpeakingHUD.Show()
In the next section, you’ll create the functionality for the Join and Leave buttons.
Join and Leave Buttons
Since agent groups control a channel’s roster, you’ll use AddMember and RemoveMember on RedGroup and BlueGroup to assign and remove players, ensuring that players can only be a part of one channel at a time. Using Report, you’ll add on-screen text for the following situations:
A player (from any team) successfully joins Red.
A player (from any team) successfully joins Blue.
A player leaves both channels.
To create this functionality, follow these steps:
Paste the following code inside
OnBegin, below setBlueChannel:VerseJoinRedButton.InteractedWithEvent.Subscribe(OnJoinRed) JoinBlueButton.InteractedWithEvent.Subscribe(OnJoinBlue) LeaveButton.InteractedWithEvent.Subscribe(OnLeave)Paste the following code inside
voice_channel_test_device, belowRegister:VerseOnJoinRed(Agent:agent):void= BlueGroup.RemoveMember(Agent) RedGroup.AddMember(Agent, test_voice_member_info{}) Report("A Player joined Red. Red has {RedGroup.GetMemberMap().Length}, Blue has {BlueGroup.GetMemberMap().Length}.") OnJoinBlue(Agent:agent):void= RedGroup.RemoveMember(Agent) BlueGroup.AddMember(Agent, test_voice_member_info{}) Report("A Player joined Blue. Blue has {BlueGroup.GetMemberMap().Length}, Red has {RedGroup.GetMemberMap().Length}.")
In the next section, you’ll create the functionality for the Toggle Mute button.
Toggle Mute Button
Setting CanBroadcast to false mutes a player, and setting it to true lets them speak again, all without changing their agent group. This is useful if a player is eliminated and shouldn’t be able to speak to teammates. Using Report, you’ll add on-screen text for the following situations:
A player cannot be muted (only players in a channel can be muted).
A player is successfully muted.
A player is successfully unmuted.
To create this functionality, follow these steps:
Paste the following code inside
OnBegin, below theLeaveButtonsubscription:VerseToggleMuteButton.InteractedWithEvent.Subscribe(OnToggleMute)Paste the following code inside
voice_channel_test_device, belowOnLeave:VerseOnToggleMute(Agent:agent):void= if (Info := RedGroup.GetMemberMap()[Agent]): FlipCanBroadcast(Info) RedGroup.AddMember(Agent, Info) Report(MuteText("Red", Info)) else if (Info := BlueGroup.GetMemberMap()[Agent]): FlipCanBroadcast(Info) BlueGroup.AddMember(Agent, Info) Report(MuteText("Blue", Info)) else:
In the next section, you’ll create the functionality for the Toggle Channel button.
Toggle Channel Button
Switching a channel on or off without changing its roster can be useful when players are between rounds, in a lobby, or during a cutscene. You can control whether a channel is on or off by calling Disable() or Enable() and using a variable (ChannelsEnabled) that remembers the channel's status. Using Report, you’ll add on-screen text for the following situations:
Both channels are successfully enabled.
Both channels are successfully disabled.
To create this functionality, follow these steps:
Paste the following code inside
voice_channel_test_device, belowvar BlueChannel:Versevar ChannelsEnabled:logic = truePaste the following code inside
OnBegin, below setBlueChannel, above the button subscriptions:VerseToggleChannelsButton.InteractedWithEvent.Subscribe(OnToggleChannels)Paste the following code inside
voice_channel_test_device, belowMuteText:VerseOnToggleChannels(Agent:agent):void= if (ChannelsEnabled?): set ChannelsEnabled = false if (Red := RedChannel?): Red.Disable() if (Blue := BlueChannel?): Blue.Disable() Report("Red and Blue channels disabled.") else: set ChannelsEnabled = true
In the next section, you’ll add additional functionality to detect and report when a player from a certain channel is speaking.
Detect Speaking
A channel can tell you when a player starts and stops speaking through BeginBroadcastEvent and EndBroadcastEvent. In a game, you can use this to show a speaking icon above a player or trigger NPC behavior. Using ReportSpeaking, you’ll trigger on-screen messages for the following situations:
A player in Red started or stopped speaking.
A player in Blue started or stopped speaking.
To create this functionality, follow these steps:
Paste the following code inside
OnBegin, below theToggleChannelsButtonsubscription:Verseif (Red := RedChannel?): Red.BeginBroadcastEvent().Subscribe(OnRedBeginSpeaking) Red.EndBroadcastEvent().Subscribe(OnRedEndSpeaking) if (Blue := BlueChannel?): Blue.BeginBroadcastEvent().Subscribe(OnBlueBeginSpeaking) Blue.EndBroadcastEvent().Subscribe(OnBlueEndSpeaking)Paste the following code inside
voice_channel_test_device, belowOnToggleChannels:VerseOnRedBeginSpeaking(Agent:agent):void= ReportSpeaking("Voice test: someone in Red started speaking") OnRedEndSpeaking(Agent:agent):void= ReportSpeaking("Voice test: someone in Red stopped speaking") OnBlueBeginSpeaking(Agent:agent):void= ReportSpeaking("Voice test: someone in Blue started speaking") OnBlueEndSpeaking(Agent:agent):void=Click File > Save and Compile.
By now, your Verse file should look like the code below:
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/AgentGroup }
using { /Verse.org/Chat }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
test_voice_member_info := class(has_voice_member_info) {}
In the next section, you’ll add all button devices and HUD Message devices to the map and hook them up to your voice channel device.
Test Your Device in an Island
To test your device, follow these steps:
In the Content Browser, locate your device (voice_channel_test_device) and drag an instance into the viewport.
Locate the button device and drag five instances into the viewport at a height that a player can reach.
Locate the HUD Message Device and drag two instances into the viewport
Click on your device. From the Details Panel, use the eyedropper tool to assign one button to each function.
Assign a HUD Message Device to ActionHUD, and another to SpeakingHUD.
Compile and Launch Session.
You can now test your work in a Launch Session or with playtesters. If you’re testing with a party, all party members must have Game Chat selected in their Voice settings because Party Chat will override Game Chat.
Use billboard devices to label your buttons to help your play testers understand what each button does.