본문으로 건너뛰기

SyncVar Collections

네트워크 상에서 컬렉션을 동기화할 때 사용하는 특별한 컬렉션 타입들입니다. 서버에서 컬렉션이 변경되면 자동으로 모든 클라이언트에 전파됩니다.

SyncList

순서가 있는 데이터 목록을 동기화할 때 사용합니다. 퀘스트 목록, 인벤토리 등을 구현할 때 유용합니다.

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

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

// 초기 인벤토리 로드
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)
{
// 새 아이템 획득 UI 표시
UIManager.Instance.ShowNewItemNotification(items[index]);
}

void OnItemRemoved(int index, int oldValue)
{
// 인벤토리 UI 업데이트
UIManager.Instance.UpdateInventoryUI();
}
}

SyncDictionary

키-값 쌍의 데이터를 동기화할 때 사용합니다. 장비 시스템, 스킬 시스템 등을 구현할 때 유용합니다.

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)
{
// 장비 변경 효과 표시
VFXManager.Instance.PlayEquipEffect(slot);
// 캐릭터 외형 업데이트
CharacterCustomization.Instance.UpdateEquipment(slot, equipment[slot]);
}
}

SyncHashSet

중복되지 않는 데이터 집합을 동기화할 때 사용합니다. 획득한 업적, 해금된 콘텐츠 등을 구현할 때 유용합니다.

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))
{
// 업적 달성 보상 지급 등의 서버 로직
}
}

void OnAchievementUnlocked(string achievementId)
{
// 업적 달성 UI 표시
UIManager.Instance.ShowAchievementPopup(achievementId);
// 업적 효과음 재생
AudioManager.Instance.PlayAchievementSound();
}
}

SyncSortedSet

자동으로 정렬되는 중복되지 않는 데이터 집합을 동기화할 때 사용합니다. 랭킹 시스템, 점수판 등을 구현할 때 유용합니다.

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

public int CompareTo(ScoreData other) => other.score.CompareTo(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)
{
// 리더보드 UI 업데이트
UIManager.Instance.UpdateLeaderboard(leaderboard);
}
}
노트
  1. 모든 SyncVar 컬렉션은 서버에서만 수정해야 합니다
  2. 클라이언트는 OnStartClient에서 이벤트 핸들러를 등록하고, OnStopClient에서 제거해야 합니다
  3. 초기 데이터는 이벤트 핸들러 등록 전에 이미 동기화되어 있으므로, 필요한 경우 수동으로 처리해야 합니다
  4. OnChange는 범용 이벤트이므로 가능한 구체적인 이벤트(OnAdd, OnRemove 등)를 사용하는 것이 좋습니다
  5. 컬렉션은 readonly로 선언하여 인스턴스가 변경되는 것을 방지합니다