-
Notifications
You must be signed in to change notification settings - Fork 41
DisplayKit SendingToPlayers
davidsebesta edited this page Jun 14, 2026
·
9 revisions
This guide covers how to spawn canvases on all (and specific!) players, as well as controlling their visibility.
- Understanding Canvas Scope
- Spawning to All Players
- Spawning to Specific Players
- Visibility Control
- Canvas Events
Important
DisplayKit canvases can be either per-player or global. Understanding the difference is crucial.
- Each player gets their own unique canvas
- Changes affect only that specific player's view
- Use when each player needs unique content
- Examples: Health bars, inventory, role displays, personal stats
// Per-player canvas - each player gets their own
DisplayCanvas playerCanvas = DisplayCanvas.Create();
playerCanvas.Spawn(playerConnectionId);- Single canvas shared across all spawned players
- Changes affect ALL observers simultaneously
- Use for shared UI that everyone sees
- Examples: Server announcements, countdown timers, scoreboards
// Global canvas - all players see the same thing
DisplayCanvas globalCanvas = DisplayCanvas.Create();
globalCanvas.Spawn(); // Spawns to all current and future players| Feature | Per-Player | Global |
|---|---|---|
| Created per player | Yes | No |
| Changes affect | One player | All players |
| Memory usage | Higher | Lower |
| Network traffic | Per player | Broadcast once |
| Best for | Personal UI | Shared UI |
| Spawn method | Spawn(connectionId) |
Spawn() |
// Spawn to all current AND future players (global canvas)
canvas.Spawn();
// Canvas will be visible by default based on DefaultVisibility
canvas.DefaultVisibility = CanvasVisibility.Visible;public partial class AnnouncementSystem : CustomEventsHandler
{
private DisplayCanvas _announcementCanvas;
private DisplayText _announcementText;
public override void OnServerWaitingForPlayers()
{
_announcementCanvas = DisplayCanvas.Create();
_announcementCanvas.DefaultVisibility = CanvasVisibility.Hidden;
// ... setup UI elements ...
_announcementText = _announcementCanvas.AddText();
_announcementText.Text.Font = FontType.RobotoBold;
_announcementText.Text.FontSize = 32f;
_announcementText.Text.Color = Color.white;
_announcementText.Text.Align = TextAnchor.MiddleCenter;
_announcementText.Spacing.MarginBottom = 10f;
// Global canvas - spawns to all players (current and future)
_announcementCanvas.Spawn();
}
public void ShowAnnouncement(string message)
{
// Update and show
_announcementText.Content = message;
_announcementCanvas.Show();
}
public void HideAnnouncement()
{
_announcementCanvas.Hide();
}
}When using canvas.Spawn() without parameters:
- Current players receive the canvas immediately
- New players (late joiners) automatically receive the canvas when they connect
- This makes it ideal for persistent UI like round timers or server info
// Spawn to specific player by connection ID (per-player canvas)
canvas.Spawn(connectionId);
// Spawn to specific player by ReferenceHub
ReferenceHub player = ...;
canvas.Spawn(player);public class HealthBarUI : CustomEventsHandler
{
private Dictionary<int, PlayerHealthData> playerHealthBars = new Dictionary<int, PlayerHealthData>();
public override void OnPlayerJoined(PlayerJoinedEventArgs ev)
{
// Create unique canvas for this player
DisplayCanvas canvas = DisplayCanvas.Create();
canvas.DefaultVisibility = CanvasVisibility.Visible;
// ... setup health bar UI ...
// Spawn only to this player
canvas.Spawn(ev.Player);
playerHealthBars[ev.Player] = new PlayerHealthData(...);
}
public void UpdatePlayerHealth(Player player)
{
// Update only this player's health bar
if (playerHealthBars.TryGetValue(player, out PlayerHealthData data))
{
data.HealthText.Content = $"{player.Health:F0} / {data.MaxHealth:F0}";
}
}
}Note: For a full example, see Examples page.
// Show canvas to all observers
canvas.Show();
// Hide canvas from all observers
canvas.Hide();
// Set visibility explicitly
canvas.SetVisibility(true); // Show
canvas.SetVisibility(false); // Hide// Show to specific player
canvas.Show(connectionId);
canvas.Show(player);
canvas.Show(referenceHub);
// Hide from specific player
canvas.Hide(connectionId);
canvas.Hide(player);
canvas.Hide(referenceHub);
// Set visibility explicitly
canvas.SetVisibility(player, true);
canvas.SetVisibility(player, false);public class CanvasShowKeybind : CustomEventsHandler
{
private const int KeybindId = 1;
private DisplayCanvas _scoreboardCanvas;
public override void OnServerWaitingForPlayers()
{
ServerSpecificSettingsSync.DefinedSettings = new ServerSpecificSettingBase[]
{
new SSGroupHeader("Misc"),
new SSKeybindSetting(KeybindId, "Show canvas", KeyCode.Tab, hint: $"Show super cool canvas"),
};
ServerSpecificSettingsSync.SendToAll();
ServerSpecificSettingsSync.ServerOnSettingValueReceived += ProcessUserInput;
_scoreboardCanvas = DisplayCanvas.Create();
_scoreboardCanvas.DefaultVisibility = CanvasVisibility.Hidden;
// setup the scoreboard for your needs...
}
private void ProcessUserInput(ReferenceHub sender, ServerSpecificSettingBase setting)
{
switch (setting.SettingId)
{
case KeybindId when setting is SSKeybindSetting keybind:
{
if (keybind.SyncIsPressed)
_scoreboardCanvas.Show(sender);
else
_scoreboardCanvas.Hide(sender);
}
break;
}
}
}// Canvas starts visible when constructed
canvas.DefaultVisibility = CanvasVisibility.Visible;
// Canvas starts hidden when constructed
canvas.DefaultVisibility = CanvasVisibility.Hidden;public class GlobalTimerUI : CustomEventsHandler
{
private DisplayCanvas _timerCanvas;
private DisplayText _timerText;
public override void OnServerRoundStarted()
{
_timerCanvas = DisplayCanvas.Create();
_timerCanvas.DefaultVisibility = CanvasVisibility.Visible;
// ... setup timer UI ...
_timerText = _timerCanvas.AddText();
// setup the text...
// Spawn to ALL players (current and future)
_timerCanvas.Spawn();
}
public void UpdateTime(int secondsRemaining)
{
// Update affects ALL players simultaneously
_timerText.Content = secondsRemaining.ToString();
}
}public class RoleDisplayUI : CustomEventsHandler
{
private Dictionary<Player, DisplayCanvas> _playerCanvases = new Dictionary<Player, DisplayCanvas>();
public override void OnPlayerJoined(PlayerJoinedEventArgs ev)
{
// Create canvas for this specific player
DisplayCanvas canvas = DisplayCanvas.Create();
canvas.DefaultVisibility = CanvasVisibility.Visible;
// ... setup role display ...
// Spawn ONLY to this player
canvas.Spawn(ev.Player);
_playerCanvases[ev.Player] = canvas;
}
public override void OnPlayerLeft(PlayerLeftEventArgs ev)
{
// Clean up this player's canvas
if (_playerCanvases.TryGetValue(ev.Player, out DisplayCanvas canvas))
{
canvas.Destroy();
_playerCanvases.Remove(ev.Player);
}
}
}- Element Reference - Complete canvas API documentation
- Examples - See practical per-player and global canvas examples