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