Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/문법

[Unity] 유니티 C#) 자료구조 딕셔너리(Dictionary)

새벽_글쓴이 2024. 10. 28. 21:03
반응형

딕셔너리는 왜 사용할까?

딕셔너리는 많은 데이터안에서 특정한 한 데이터를 찾을때 빛을 발한다.

예를 들어, RPG게임에서 아이템을 찾는다고 가정해보자

List<string> itemList = new List<string>() { "A", "B", "C" };
string findInList = itemList.Find(x => x == "B"); // 전체 순회 필요

예시에는 A,B,C 3가지만 들어있지만 RPG게임에는 수천, 수만개의 아이템이 있을 것이다.

그 중 하나의 아이템을 찾는다고 하면, 순차적으로 0번부터 탐색을 시작할 것이다.

이는 매우 비효율 적이다.

 

이때 딕셔너리로 만들면 어떨까?

Dictionary<int, string> fastLookup = new Dictionary<int, string>();

fastLookup.Add(1, "A");
fastLookup.Add(2, "B");
string findInDict = fastLookup[2]; // 즉시 "B" 반환

 

아이템의 키 값을 입력하면 키값에 해당하는 아이템을 바로 찾을 수 있다.

이러한 이유로 딕셔너리를 사용한다.


딕셔너리 선언

Dictionary<키값, 밸류값> 변수명 = new Dictionary<키값,밸류값>();

Dictionary<string, int> stringKeys = new Dictionary<string, int>();
Dictionary<int, string> intKeys = new Dictionary<int, string>();
Dictionary<Enum, string> enumKeys = new Dictionary<Enum, string>();
Dictionary<GameObject, PlayerData> objectKeys = new Dictionary<GameObject, PlayerData>();

딕셔너리의 장단점

장점

유연한 키 타입 사용 : 위의 예시처럼 다양한 타입으로 선언할 수 있기에 굉장히 자유롭다

 

키-값 쌍으로 직관적인 데이터 관리 : 아래의 예시처럼 굉장히 직관적인 데이터 관리가 가능하다  

Dictionary<string, int> scores = new Dictionary<string, int>()
    {
        {"철수", 100},
        {"영희", 95},
        {"민수", 90}
    };

 

빠른 검색 속도 : 위에서 설명했듯이 키값을 입력하면 바로 밸류값을 검색할 수 있다.


단점

메모리 사용량이 많음

키값과 밸류값을 저장하므로 메모리를 조금이라도 더 사용하게 된다.

하지만 하드웨어의 성능이 향상된 만큼 크게 의식할 필요는 없을 듯 하다.

 

순서가 보장되지 않음

Dictionary<string, int> dict = new Dictionary<string, int>();

dict.Add("A", 1);
dict.Add("B", 2);
dict.Add("C", 3);
        
foreach(var item in dict)
{
    Debug.Log(item.Key); 
}

// 결과: 입력 순서와 다르게 출력될 수 있음

 

중복 키 사용 불가능

Dictionary<string, int> dict = new Dictionary<string, int>();

dict.Add("A", 1);

try
{
    dict.Add("A", 4); // 에러 발생
}
    catch(ArgumentException e)
{
    Debug.LogError("키 중복!");
}

딕셔너리의 사용 예시

딕셔너리만 단독으로 구현이 애매한 부분이 있기 때문에 다양한 예시를 작성해 보겠다.

 

1. 아이템 시스템

public class ItemManager : MonoBehaviour
{
    // 아이템 ID로 아이템 정보 관리
    Dictionary<int, Item> itemDatabase = new Dictionary<int, Item>();
    
    void Start()
    {
        // 아이템 데이터 초기화
        itemDatabase.Add(1001, new Item { name = "체력 포션", price = 100 });
        itemDatabase.Add(1002, new Item { name = "마나 포션", price = 150 });
    }

    // 아이템 ID로 빠르게 아이템 정보 가져오기
    public Item GetItem(int itemId)
    {
        if (itemDatabase.TryGetValue(itemId, out Item item))
        {
            return item;
        }
        return null;
    }
}

 

2. 플레이어 인벤토리

public class Inventory : MonoBehaviour
{
    // 아이템 이름과 수량 관리
    Dictionary<string, int> inventory = new Dictionary<string, int>();

    // 아이템 추가
    public void AddItem(string itemName, int amount = 1)
    {
        if (inventory.ContainsKey(itemName))
        {
            inventory[itemName] += amount;
        }
        else
        {
            inventory.Add(itemName, amount);
        }
        UpdateUI();
    }

    // 아이템 사용
    public bool UseItem(string itemName)
    {
        if (inventory.ContainsKey(itemName) && inventory[itemName] > 0)
        {
            inventory[itemName]--;
            if (inventory[itemName] <= 0)
            {
                inventory.Remove(itemName);
            }
            UpdateUI();
            return true;
        }
        return false;
    }
}

 

3. 성과/업적 시스템

public class AchievementSystem : MonoBehaviour
{
    // 업적 ID와 달성 여부 관리
    Dictionary<string, bool> achievements = new Dictionary<string, bool>();
    
    void Start()
    {
        // 업적 초기화
        achievements.Add("FIRST_KILL", false);
        achievements.Add("LEVEL_10", false);
    }

    public void UnlockAchievement(string achievementId)
    {
        if (achievements.ContainsKey(achievementId) && !achievements[achievementId])
        {
            achievements[achievementId] = true;
            ShowAchievementUnlocked(achievementId);
        }
    }
}
반응형