Skip to main content

SyncVar Collections

SyncVar Collections are special collection types used to synchronize collections over the network. When the collection is modified on the server, the changes are automatically propagated to all clients.

SyncList

Used to synchronize ordered data lists, which are useful for implementing quest lists, inventories, etc.

public class Inventory : NetworkBehaviour
{
public readonly SyncList<int> items = new SyncList<int>();

public override void OnStartClient()
{
items.OnAdd += OnItemAdded;
items.OnRemove += OnItemRemoved;

// Load initial inventory
for (int i = 0; i < items.Count; i++)
items.OnAdd.Invoke(i);
}

[Server]
public void AddItem(int itemId)
{
items.Add(itemId);
}

void OnItemAdded(int index)
{
// Show new item UI
UIManager.Instance.ShowNewItemNotification(items[index]);
}

void OnItemRemoved(int index, int oldValue)
{
// Update inventory UI
UIManager.Instance.UpdateInventoryUI();
}
}

SyncDictionary

Used to synchronize key-value pair data, useful for implementing equipment systems, skill systems, etc.

public enum EquipSlot { Weapon, Armor, Helmet, Boots }

public struct EquipItem
{
public int itemId;
public int enhanceLevel;
public bool isLocked;
}

public class EquipmentSystem : NetworkBehaviour
{
public readonly SyncDictionary<EquipSlot, EquipItem> equipment = new SyncDictionary<EquipSlot, EquipItem>();

public override void OnStartClient()
{
equipment.OnSet += OnEquipmentChanged;
equipment.OnRemove += OnEquipmentRemoved;

foreach (var slot in equipment.Keys)
equipment.OnSet.Invoke(slot, default);
}

[Server]
public void EquipItem(EquipSlot slot, EquipItem item)
{
equipment[slot] = item;
}

void OnEquipmentChanged(EquipSlot slot, EquipItem oldItem)
{
// Display equipment change effect
VFXManager.Instance.PlayEquipEffect(slot);
// Update character appearance
CharacterCustomization.Instance.UpdateEquipment(slot, equipment[slot]);
}
}

SyncHashSet

Used to synchronize a set of unique data, useful for implementing achievements, unlocked content, etc.

public class AchievementSystem : NetworkBehaviour
{
public readonly SyncHashSet<string> unlockedAchievements = new SyncHashSet<string>();

public override void OnStartClient()
{
unlockedAchievements.OnAdd += OnAchievementUnlocked;

foreach (string achievementId in unlockedAchievements)
unlockedAchievements.OnAdd.Invoke(achievementId);
}

[Server]
public void UnlockAchievement(string achievementId)
{
if (unlockedAchievements.Add(achievementId))
{
// Server logic for rewarding achievement
}
}

void OnAchievementUnlocked(string achievementId)
{
// Show achievement UI
UIManager.Instance.ShowAchievementPopup(achievementId);
// Play achievement sound
AudioManager.Instance.PlayAchievementSound();
}
}

SyncSortedSet

Used to synchronize an automatically sorted set of unique data, useful for implementing ranking systems, leaderboards, etc.

public struct ScoreData : IComparable<ScoreData>
{
public string playerName;
public int score;

public int CompareTo(ScoreData other) => other.score.CompareTo(score); // Sort by highest score
}

public class LeaderboardSystem : NetworkBehaviour
{
public readonly SyncSortedSet<ScoreData> leaderboard = new SyncSortedSet<ScoreData>();

public override void OnStartClient()
{
leaderboard.OnAdd += OnScoreAdded;
leaderboard.OnRemove += OnScoreRemoved;

foreach (var score in leaderboard)
leaderboard.OnAdd.Invoke(score);
}

[Server]
public void AddScore(string playerName, int score)
{
leaderboard.Add(new ScoreData { playerName = playerName, score = score });
}

void OnScoreAdded(ScoreData score)
{
// Update leaderboard UI
UIManager.Instance.UpdateLeaderboard(leaderboard);
}
}
note
  1. All SyncVar collections should only be modified on the server.
  2. Clients should register event handlers in OnStartClient and remove them in OnStopClient.
  3. Initial data is synchronized before event handlers are registered, so manual handling might be required.
  4. Since OnChange is a general event, it's better to use more specific events like OnAdd, OnRemove, etc.
  5. Collections should be declared as readonly to prevent modification of their instance. :::