Skip to content
pluginv3.6Blueprint only

ScarCore Communication System

Multiplayer chat, voice, quick messages and ping.

ScarCore adds working multiplayer communication to your game: server-authoritative text chat, voice chat with push-to-talk, adjustable voice volume, a quick-messages panel, a per-player mute list and a live ping readout. Add one component to your PlayerController and press Play. Nothing is hard-coded to a platform, so your DefaultEngine.ini decides whether you are on Steam, EOS, LAN or a dedicated server.

Engine support
Unreal Engine 4.27 and 5.0 to 5.7
Version
3.6
Backends
Steam, EOS, LAN (Null), Dedicated Servers

What you get

  • Server-authoritative text chat with profanity filter and rate limiting
  • Voice chat that works on dedicated and direct-IP servers, not just listen servers
  • Push-to-talk, mic gain, master and per-player voice volume
  • Quick-messages panel and a per-player mute list
  • Live colour-coded ping readout
  • One component, no C++ and no input mappings to wire up
  • Pre-built UI with every feature, or reparent your own widget

What you get

ScarCore Communication System adds working multiplayer communication to your game: server-authoritative text chat, voice chat with push-to-talk, adjustable voice volume (master, per-player and mic gain), a quick-messages panel, a per-player mute list, and a live ping readout. You add one component to your PlayerController and press Play. That is the whole setup.

Everything is Blueprint-friendly and nothing is hard-coded to a platform. Your DefaultEngine.ini decides whether you are on Steam, EOS, LAN or a dedicated server, and the plugin adapts to whatever it finds.

ClassWhat it is for
ScarCore Communication ComponentAdd this to your PlayerController. Holds all settings, creates the UI, and exposes the Blueprint API.
ScarCoreBaseUIThe pre-built UI, the full feature set with zero designer work: a black-tinted chat panel with a slide button that collapses and expands it, mic and speaker buttons, a QUICK button and quick-messages list, a PLAYERS button and per-player mute list, a master volume slider, and the ping label. Toggle any part off or restyle every colour and label via properties.
ScarCoreCommunicationWidgetParent class for your own custom UI.
ScarQuickMessageRow / ScarPlayerMuteRowRow widgets for the two popups. Reparent a WBP to restyle them.

Under the hood: chat sender names are resolved on the server from PlayerState, so no spoofing, and the profanity filter and rate limiter run server-side. Voice is captured locally, Opus-compressed, and relayed over the replicated game connection, so it works on dedicated servers and direct-IP setups out of the box. A legacy OnlineSubsystem voice path is still built in for session-based games, and one toggle switches between them.

Quick start

  1. 01Install and enable. In the Epic Games Launcher, install the plugin to your engine version (4.27 to 5.7) from your Fab Library. Then in your project: Edit > Plugins, search "ScarCore", tick Enabled, restart.
  2. 02Add the component. Open your PlayerController Blueprint, click Add Component, and add ScarCore Communication Component.
  3. 03Pick the UI. Select the component and set Main Widget Class to ScarCoreBaseUI.
  4. 04Set up your platform in one click. Open Edit > Project Settings > ScarCore Communication, pick Target Platform (Steam / EOS / Local / Null), and click Apply Platform Config. It writes the DefaultEngine.ini entries for you, online subsystem plus voice. Restart the editor.

Local / Null needs no credentials. It is the one to pick for LAN, dedicated servers, direct-IP and single-machine standalone testing.

Press Play with 2 or more players on a listen server. You see the chat panel bottom-left, mic and speaker buttons above it, and the ping top-right. Press Enter to type, M to turn your mic on, hold V to talk, and N to hear everyone else.

Players join muted on purpose. The mic starts OFF and the speaker starts MUTED, so nobody broadcasts or hears anything until they press M and N. If your game wants open comms from the first second, untick Start With Speaker Muted and optionally tick Start With Mic On.

Online subsystem config

The fast way is Project Settings > ScarCore Communication > Apply Platform Config, which writes all of this for you. The blocks below are the manual equivalent and a reference for exactly what gets written. Put your chosen block in YourProject/Config/DefaultEngine.ini and restart the editor, since Unreal loads the subsystem once at startup.

LAN / local testing (Null)

[Voice]
bEnabled=true

[OnlineSubsystem]
bHasVoiceEnabled=true
DefaultPlatformService=Null

Steam

Enable the Online Subsystem Steam plugin in Edit > Plugins first, and have the Steam client running when you test.

[Voice]
bEnabled=true

[OnlineSubsystem]
bHasVoiceEnabled=true
DefaultPlatformService=Steam

[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
GameServerQueryPort=27015
bRelaunchInSteam=false
bVACEnabled=false

[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

App ID 480 is the free Valve test app and works for development. Swap in your real App ID before shipping.

Epic Online Services (EOS)

Enable the Online Subsystem EOS plugin, create an artifact at dev.epicgames.com/portal, and fill in your own ids. The encryption key must be exactly 64 hex characters.

[Voice]
bEnabled=true

[OnlineSubsystem]
bHasVoiceEnabled=true
DefaultPlatformService=EOS

[OnlineSubsystemEOS]
bEnabled=true

[/Script/OnlineSubsystemEOS.NetDriverEOS]
bIsUsingP2PSockets=true

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemEOS.NetDriverEOS",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

[/Script/OnlineSubsystemEOS.EOSSettings]
DefaultArtifactName=DefaultArtifact
bEnableOverlay=true
bEnableSocialOverlay=true
bUseEAS=true
bUseEOSConnect=true
bUseEOSSessions=true
+Artifacts=(ArtifactName="DefaultArtifact",ClientId="<id>",ClientSecret="<secret>",ProductId="<id>",SandboxId="<id>",DeploymentId="<id>",EncryptionKey="<64-hex-chars>")

Dedicated servers (optional tuning)

No special setup is needed. The component detects dedicated servers and runs no UI or timers there. Voice works on dedicated and direct-IP servers by default, because the custom relay sends compressed frames over the game connection, so no OnlineSubsystem session is required. The values below are just sensible network tuning.

[/Script/OnlineSubsystemUtils.IpNetDriver]
NetServerMaxTickRate=60
MaxClientRate=30000
MaxInternetClientRate=30000

[/Script/Engine.GameSession]
MaxPlayers=64

Mic sensitivity (optional)

[Voice]
SilenceDetectionThreshold=0.01
MicNoiseGateThreshold=0.01
MicInputGain=1.0
MicOutputGain=1.0

Mobile permissions (only if you ship there)

; Android - DefaultEngine.ini
[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings]
+ExtraPermissions=android.permission.RECORD_AUDIO
+ExtraPermissions=android.permission.MODIFY_AUDIO_SETTINGS
+ExtraPermissions=android.permission.INTERNET
+ExtraPermissions=android.permission.ACCESS_NETWORK_STATE

; iOS - DefaultEngine.ini
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
AdditionalPlistData=<key>NSMicrophoneUsageDescription</key><string>Voice chat with other players.</string>

Default controls

The widget binds these keys on its own, with no Project Settings > Input work and no Blueprint wiring. Every key is a property under the widget Class Defaults (ScarCore | Input | Auto-Bindings) if you want different ones, and Auto Register Key Bindings = false turns the whole thing off so you can wire your own.

KeyDoes
EnterFocus the chat box, send what you typed, or restore the chat UI after Escape hid it.
V (hold)Push-to-talk. Only transmits while the mic toggle is ON.
MMic toggle on / off.
NSpeaker toggle, mute or unmute all incoming voice.
COpen or close the quick-messages panel.
Up / DownMove the quick-message selection. It wraps around.
EscapeClose the quick-messages panel. Press again to hide the chat UI.
TabOpen or close the per-player mute list.
Mouse wheelScroll the chat. While the quick-messages panel is open, moves the selection instead.

While the chat box has focus, keys type into it. Enter sends and hands control back to the game.

The settings you will actually touch

Everything lives on the component, in the Details panel under the ScarCore categories. These are the ones that matter day-to-day. The rest, such as colours, rate limits and UI visibility toggles, are right next to them and self-explanatory.

SettingWhat it doesDefault
Main Widget ClassWhich UI to spawn. ScarCoreBaseUI or your own widget.(none)
Start With Mic OnSpawn with the mic already transmitting-ready.false
Start With Speaker MutedSpawn deaf until the player presses N.true
Use Push To TalkOn = hold V to talk. Off = open mic while the toggle is ON.true
Push To Talk KeyThe push-to-talk key.V
Use Custom Voice RelayOn = self-hosted Opus relay over the game connection, which works on dedicated and direct-IP servers with no session. Off = legacy OnlineSubsystem voice for listen-server and session setups.true
Voice ModeGlobal = hear everyone. Proximity = hear only nearby players.Global
Voice Output VolumeStarting master volume for incoming voice. A slider or Blueprint can change it live.1.0
Mic Input GainMultiplier on this player own mic before it is sent.1.0
Proximity RadiusHearing range in cm for Proximity mode.1200
Max Message LengthChat messages are truncated past this.256
Profanity Filter Enabled + Blocked WordsServer-side word filter. The shipped word list is a placeholder, so add your own.on
Chat Font SizeText size in the chat log.14
Ping Good / Medium ThresholdColour steps for the ping label: green, yellow, red.50 / 100

Build your own UI

Optional. ScarCoreBaseUI already ships every feature: chat, mic and speaker, quick messages, the per-player mute list, a volume slider and ping. Only build a custom widget if you want a different look.

Design a normal Widget Blueprint with any layout, art and animations you want. The plugin finds its widgets by name and wires them up automatically.

  1. 01Content Browser > right-click > User Interface > Widget Blueprint, and pick ScarCoreCommunicationWidget as the parent class. For an existing WBP, open it and use File > Reparent Blueprint.
  2. 02Design your layout. Wherever a feature should live, add the matching widget from the table below and rename it to the exact name shown.
  3. 03Tick Is Variable on each of those widgets, at the top of the Details panel.
  4. 04On the component, set Main Widget Class to your new widget. Chat, voice, popups and key bindings all work in your layout.

Names are case-sensitive and every widget is optional. Skip what you do not need: a missing widget just means that feature has no UI. Nothing breaks.

The named widgets

Name it exactlyWidget typeWhat it powers
ChatScrollBoxScroll BoxChat messages appear here, auto-scrolled.
ChatInputTextBoxEditable Text BoxThe typing field. Enter sends.
SendButtonButtonSends the typed text.
ChatPanelAny panelOptional wrapper around the chat, hidden when the chat UI is disabled.
MicButtonButtonMic toggle. Gets your on and off icons stamped on it.
SpeakerButtonButtonSpeaker toggle. Gets your on and off icons too.
VoiceVolumeSliderSliderOptional. Master incoming-voice volume, auto-wired with no Blueprint. Set Min 0 and Max 1, or 2 for boost.
VoicePanelAny panelOptional wrapper around the voice buttons.
PingTextBlockText BlockLive ping, colour-coded by your thresholds.
QuickMessagesPanelVertical BoxQuick-message rows spawn in here. Set it Collapsed by default; C opens it.
QuickMessagesButtonButtonOptional on-screen button that toggles the panel.
PlayerListPanelVertical BoxMute-list rows spawn in here.
PlayerListContainerBorder (or any widget)Optional styled wrapper around PlayerListPanel; the whole thing shows and hides together. Set it Collapsed by default; Tab opens it.
OpenPlayerListButtonButtonOptional on-screen button for the mute list. Hides while the speaker is muted, which is configurable.

A layout that works

Canvas Panel
  ChatPanel            Vertical Box      bottom-left
    ChatScrollBox      Scroll Box
    HorizontalBox
      ChatInputTextBox Editable Text Box
      SendButton       Button
  VoicePanel           Horizontal Box    above the chat
    MicButton          Button
    SpeakerButton      Button
  PingTextBlock        Text Block        top-right
  QuickMessagesPanel   Vertical Box      centered, Collapsed
  PlayerListContainer  Border            right side, Collapsed
    PlayerListPanel    Vertical Box
  OpenPlayerListButton Button            near the voice row

Icons and styling

In your widget Class Defaults you will find texture slots for every state: Mic On / Off Icon, Speaker On / Off Icon, icons for the open-list button, and per-row speaker icons for the mute list. Assign a texture and the plugin stamps it onto the button whenever the state changes, with hover and pressed tints applied for free. One texture per state is enough. Leave a slot empty to keep whatever brush you designed.

Custom popup rows

  • Quick messages: make a WBP with parent ScarQuickMessageRow, add a Button named RowButton and a Text Block named RowLabel, then set Quick Message Row Class on your main widget.
  • Mute list: make a WBP with parent ScarPlayerMuteRow, add a Button named MuteButton and a Text Block named NameText, then set Player Mute Row Class.

Animation hooks

Four events fire on your widget so you can play UMG animations: BP On Player List Show / Hide Requested when Tab opens or closes the mute list, and BP On Chat UI Hide / Show Requested when Escape hides the chat and Enter brings it back. Visibility and the mouse cursor are already handled by the time they fire, so the animation is pure polish.

Quick messages and the mute list

Quick messages

Canned phrases players send without typing. Fill the Quick Messages array in your widget Class Defaults, one entry per row, in order. In game: C opens the panel, Up and Down pick, Enter sends, Escape closes. Messages go through the normal chat pipeline, filter and rate limit included. The panel auto-closes after sending and shows the mouse cursor while open, both configurable.

Per-player mute list

Tab opens a roster of every other player in the session with a speaker icon per row. Click to mute or unmute that player locally. The muted player is not notified, nobody else is affected, and the choice sticks for the whole match, even across a reconnect. The list refreshes itself every second while open, and works on clients as well as the host.

From Blueprint, Mute Player, Is Player Muted and Get Active Remote Voice Players on the component let you build the same feature into your own scoreboard instead.

Blueprint API

Component functions

FunctionDoes
Send Chat MessageSend text to all players with default colours.
Send Chat Message ColoredSend with custom name and body colours, for team chat or announcements.
Add Local MessageShow a message on this screen only. Never replicated.
Add Blocked Word / Set Profanity Filter EnabledManage the word filter at runtime.
Toggle Mic / Toggle SpeakerSame as pressing M or N.
Hard Mute Mic / Unhard Mute MicForce-silence the mic, overriding everything. For settings menus.
Set Voice ModeSwitch Global or Proximity at runtime.
Set / Get Voice Output VolumeMaster volume for all incoming voice on this client. Wire to a slider (0-1).
Set / Get Player Voice VolumePer-player incoming volume by net id, to turn individual players up or down. Local, and persists across their reconnect.
Set / Get Mic Input GainHow loud this player own mic transmits, as a multiplier.
Set Debug Voice LoopbackHear your own mic looped back through the full pipeline. A one-machine voice test; leave OFF for real play.
Mute Player / Is Player MutedLocal per-player mute by unique net id.
Get Active Remote Voice PlayersIds and display names of everyone else in the session.
Is Mic Toggle Enabled / Is Mic Hard Muted / Is Speaker Muted / Is TransmittingState queries.
Get Current Ping MsPing in ms. It is 0 on the listen-server host, since there is no round trip, and that is correct.

Widget functions

FunctionDoes
Focus / Unfocus Chat Input, On Enter PressedDrive the chat flow from your own input events.
Toggle / Open / Close Quick MessagesControl the quick-message panel.
Select Previous / Next, Send Selected Quick MessageKeyboard navigation, your way.
Open / Close / Toggle Player List Panel, Refresh Player Mute ListControl the mute popup.
Scroll Up / Scroll DownChat scrolling, or selection movement while the panel is open.
Apply Feature VisibilityRe-apply chat, voice and ping visibility after changing component toggles.

Events

EventFires when
On Message Received (component and widget)A chat message arrived. Play a sound, flash the HUD.
On Mic State Changed / On Speaker State ChangedThe toggles flipped. Update your own indicators.
On Remote Player Talking Changed (widget)A remote player started or stopped talking.
BP On Player List Show / Hide Requested (widget)Mute popup opened or closed. Play your animation.
BP On Chat UI Hide / Show RequestedEscape hid the chat, or Enter restored it.

Five-minute recipes

  • Welcome message: PlayerController BeginPlay, branch Is Local Player Controller, Delay 0.5s, then Add Local Message with sender "System".
  • Server announcement: a Run-on-Server event that calls Send Chat Message Colored with your announcement colour.
  • Mute checkbox in your settings menu: checked = Hard Mute Mic, unchecked = Unhard Mute Mic.
  • Talking indicator over heads: override On Remote Player Talking Changed, find the matching PlayerState in the GameState Player Array, and toggle an icon on their pawn.
  • Mute from your scoreboard: Get Active Remote Voice Players for the roster, Is Player Muted for current state, and Mute Player on your button.
  • Ping in your own HUD: a 1s timer that calls Get Current Ping Ms and writes it to your text block.
  • Voice volume slider: drop a Slider named VoiceVolumeSlider (Min 0, Max 1) into your widget and it auto-controls master voice volume with no wiring. For a settings menu, bind your own slider On Value Changed to Set Voice Output Volume instead.
  • Per-player volume: build a row list from Get Active Remote Voice Players, give each row a slider, and call Set Player Voice Volume with the player id and value. Use Set Mic Input Gain for the player own transmit level.

Test it, then ship it

Testing chat and voice on one PC

Play dropdown > Number of Players = 2, Net Mode = Play As Listen Server. For chat, keeping Run Under One Process is fine: type in one window and watch it in both. For voice, untick Run Under One Process so each player is its own standalone process, since they would otherwise share one audio session.

Both windows share your single mic, so split the roles: in the host window press M for mic on, and in the client window press N for speaker on. Talk, and the client plays your voice back. With Use Push To Talk off, M and N behave like a normal game. With it on, hold V to talk.

Hear yourself with no second player. Call Set Debug Voice Loopback (true) on the component, or tick Debug Voice Loopback in its Details, and just talk. It starts the mic on its own and echoes you through the full capture, Opus, decode and playback path. No mic toggle, no push-to-talk, no server needed. Turn it OFF for real matches.

This is the number one thing that fools people. A background (unfocused) window is muted by default, so on one PC you hear your own loopback in the focused window but never the other player voice, which plays in the unfocused window. Apply Platform Config now writes the fix for you (UnfocusedVolumeMultiplier=1.0 under [/Script/Engine.Engine]). If you configured the ini by hand, add that line yourself.

Shipping checklist

  • DefaultEngine.ini has the voice block plus your platform block.
  • Steam: real App ID (not 480) and the Online Subsystem Steam plugin enabled.
  • EOS: real artifact ids and a 64-character hex encryption key.
  • Component on the PlayerController your shipped GameMode actually uses, with Main Widget Class set.
  • Custom UI: parent class is ScarCoreCommunicationWidget, named widgets spelled exactly, Is Variable ticked.
  • Startup states reviewed: Start With Mic On and Start With Speaker Muted match your design.
  • Voice path chosen: Use Custom Voice Relay stays ON for dedicated and direct-IP servers; flip OFF only for session-based OSS voice. Debug Voice Loopback is OFF.
  • Blocked Words filled with a real list, and Quick Messages filled if you use the panel.
  • Default keys do not clash with your game bindings; rebind in Class Defaults if they do.
  • Mic permissions added for Android and iOS if you ship there.
  • One Shipping build, two real players, chat and voice confirmed.

When something is off

SymptomFix
I cannot hear anyoneThe speaker starts muted by design, so press N. Also check Tab: you may have muted them earlier.
No one hears meThe mic starts OFF, so press M first. Push-to-talk only transmits while V is held and the mic is ON. Check Windows mic permissions under Settings > Privacy > Microphone.
Voice does not work at allThe default custom relay still needs [Voice] bEnabled=true, a DefaultPlatformService for player identity, and an editor restart after editing the ini, but it does NOT need an online session. Check Windows mic permissions. Legacy path only: it also needs bHasVoiceEnabled=true, a live session, and on Steam the client running with the plugin enabled.
No UI appearsMain Widget Class is not set, Auto Create UI is unticked, or the component is not on a PlayerController. The Output Log, filtered to LogScarCoreCommunication, tells you which.
Chat only shows on my screenYou are in single-player. Set Number of Players to 2 or more and Net Mode to Play As Listen Server.
Some players are silent in Proximity modeThey are outside Proximity Radius. That is the feature: raise the radius or switch to Global.
My custom widget buttons do nothingA name is off by one character, since they are case-sensitive, or Is Variable is not ticked, or the parent class is not ScarCoreCommunicationWidget.
Tab shows an empty listThe list excludes you, so it is empty until someone else joins. In a custom widget the container must be named PlayerListPanel exactly.
Quick messages do not show upThe Quick Messages array is empty, or your panel is not named QuickMessagesPanel.
Keys clash with my gameEvery key is rebindable in the widget Class Defaults, or set Auto Register Key Bindings = false and call the widget functions from your own input events.

License and support

You can use the plugin in unlimited personal and commercial games, customise it through Blueprint children, and ship it inside your packaged game on any platform.

You cannot resell or redistribute the plugin itself, upload it anywhere, or bundle it in tools or asset packs meant for other developers.

Stuck? Check the troubleshooting section first, then look for LogScarCoreCommunication lines in the Output Log. The plugin says what it is doing.

Stuck on something?

We answer every serious message ourselves. Discord is the fastest way to get an answer from the person who built the plugin.