Unity的C#編程教程_59_字典 Dictionary 詳解及應用練習

目錄:

C# Dictionary: Introduction

  • 字典
    • key 和 value 的配對

依然使用 Item 腳本作為案例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable] // 在 Inspector 中可見
public class Item
{
    public string name;
    public int id;
    public Sprite icon;

}

建立 ItemDatabase 掛載到 Main Camera 上面:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    public List<Item> itemList; // 創建一個物品的列表

    public Dictionary<int, Item> itemDictionary = new Dictionary<int, Item>(); // 創建一個物品的字典並初始化(初始化是必須的)
    // key 的類型為 int,value 的類型為 Item
    // key 和 value 形成配對

    // Start is called before the first frame update
    void Start()
    {
        Item sword = new Item(); // 初始化一個物品
        sword.name = "Sword"; // 設定物品的名字
        sword.id = 0; // 設定物品的 id

        itemList.Add(sword); // 為物品列表添加一個元素
        itemDictionary.Add(sword.id, sword); // 為物品字典添加一個元素

        // 使用列表的時候,我們需要通過遍歷整個列表來查找某個元素
        // 使用字典的時候,我們可以通過物品的 id 直接查找到對應的元素

        var item = itemDictionary[sword.id];
        Debug.Log(item.name); // 通過 sword 的 id 就可以查找到對應物品
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

C# Dictionary: Looping through Dictionary

  • 循環遍歷字典元素

建立 Item:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable] // 在 Inspector 中可見
public class Item
{
    public string name;
    public int id;
    public Sprite icon;
}

建立 ItemDatabase:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    public Dictionary<int, Item> itemDictionary = new Dictionary<int, Item>();
    // 創建一個物品的字典並初始化(初始化是必須的)

    // Start is called before the first frame update
    void Start()
    {
        Item sword = new Item(); // 初始化一個物品
        sword.name = "Sword"; // 設定物品的名字
        sword.id = 0; // 設定物品的 id

        Item axe = new Item();
        axe.name = "Axe";
        axe.id = 1;

        Item bike = new Item();
        bike.name = "Bike";
        bike.id = 2;

        itemDictionary.Add(sword.id, sword); // 為物品字典添加一個元素
        itemDictionary.Add(axe.id, axe);
        itemDictionary.Add(bike.id, bike);

        // 遍歷字典:
        foreach(KeyValuePair<int,Item> item in itemDictionary)
        {
            Debug.Log("Key: " + item.Key);
            Debug.Log("Value: " + item.Value.name);
        }
        // 這裡我們也可以寫成 foreach(var item in itemDictionary)

        // 遍歷字典的 key:
        foreach(var key in itemDictionary.Keys)
        {
            Debug.Log("Key: " + key);
        }
        // 這裡的 key 是 int 類型
        // 所以也可以寫成 foreach(int key in itemDictionary.Keys)

        // 遍歷字典的 value:
        foreach (var value in itemDictionary.Values)
        {
            Debug.Log("Item Name: " + value.name);
        }

    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

注意:字典中,key 值是不能有重複的,value 可以重複。

另外,在字典中查找的時候,輸入的 key 必須存在,否則會報錯,為了避免這種情況,可以在前面插入一個檢查的程式:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    public Dictionary<int, Item> itemDictionary = new Dictionary<int, Item>();
    // 創建一個物品的字典並初始化(初始化是必須的)

    // Start is called before the first frame update
    void Start()
    {
        Item sword = new Item(); // 初始化一個物品
        sword.name = "Sword"; // 設定物品的名字
        sword.id = 0; // 設定物品的 id

        Item axe = new Item();
        axe.name = "Axe";
        axe.id = 1;

        Item bike = new Item();
        bike.name = "Bike";
        bike.id = 2;

        itemDictionary.Add(sword.id, sword); // 為物品字典添加一個元素
        itemDictionary.Add(axe.id, axe);
        itemDictionary.Add(bike.id, bike);

        if (itemDictionary.ContainsKey(60)) // 檢測 60 號物品是否存在
        {
            Debug.Log(itemDictionary[60].name); // 存在的話列印名字
        }
        else
        {
            Debug.Log("Key does not exist."); // 否則列印不存在
        }

        if (itemDictionary.ContainsKey(1)) // 檢測 1 號物品是否存在
        {
            Debug.Log(itemDictionary[1].name); // 存在的話列印名字
        }
        else
        {
            Debug.Log("Key does not exist."); // 否則列印不存在
        }

    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

C# Dictionary: When to Use

  • 什麼時候使用字典
    • 當我們在操作大型的列表時候,該用字典會更為便利
    • 比如我們的道具系統,玩家購買道具的時候,發出指令(輸入對應的物品 id)
    • 如果使用列表,我們需要遍歷整個列表來查找該物品,而使用字典的話可以直接通過 key 和 value 配對找到
    • 另外比如我們的物品欄,每個空格對應一個 key,然後可以鏈接不同的物品(即 value)

C# Dictionary: Using Dictionary for Player Connections

  • 在線玩家監測系統
    • 每個玩家登陸遊戲的時候分配一個 id
    • 使用字典把 id 和玩家進行配對組合
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player
{
    public string name;
    public int id;

    public Player(int id) // 構造函數,id是必須的屬性
    {
        this.id = id;
    }
}


public class Main : MonoBehaviour
{
    public Dictionary<int, Player> playersDict = new Dictionary<int, Player>();
    // 設定一個登陸玩家的字典,並初始化

    Player p1;
    Player p2;

    // Start is called before the first frame update
    void Start()
    {
        p1 = new Player(21); // 登陸一個玩家,分配一個 id
        p1.name = "AA";

        p2 = new Player(34);
        p2.name = "BB";

        playersDict.Add(p1.id, p1); // 把登陸的玩家添加到玩家字典
        playersDict.Add(p2.id, p2);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) // 按下空格鍵
        {
            if (playersDict.ContainsKey(34)) // 查詢玩家 id 是否存在
            {
                Debug.Log("Player Name: " + playersDict[34].name); // 存在的話列印該玩家名字
            }
            else
            {
                Debug.Log("ID not exist!"); // 玩家 id 不存在
            }
        }
    }
}

運行後,會列印 p2 的名字。

C# Dictionary: Using Dictionary with Primitive Types

  • 在字典中使用一些預設的類型,比如 int 和 string

設定一個字典,組成名字和年齡的配對:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Main : MonoBehaviour
{
    public Dictionary<string, int> player = new Dictionary<string, int>();
    // 建立一個字典,並初始化,key 為玩家名字,value 為玩家年齡

    // Start is called before the first frame update
    void Start()
    {
        player.Add("AA", 20); // 添加玩家
        player.Add("BB", 21);
        player.Add("CC", 34);

        int age = player["BB"]; // 獲得第二個玩家的年齡

        Debug.Log("The age of BB is " + age); // 顯示年齡
    }

    // Update is called once per frame
    void Update()
    {

    }
}

注意:字典只可以通過 key 來查找 value,而不能反過來。

再設計一個 book 的字典:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Main : MonoBehaviour
{
    public Dictionary<int, string> book = new Dictionary<int, string>();
    // 建立一個字典,並初始化,key 為玩家名字,value 為玩家年齡

    // Start is called before the first frame update
    void Start()
    {
        book.Add(123, "Good to go"); // 添加書本
        book.Add(22, "What is that");
        book.Add(25, "How to sell");

        foreach(KeyValuePair<int,string> item in book) // 列印所有書目
        {
            Debug.Log("ID: " + item.Key + " Book: " + item.Value);
        }

    }

    // Update is called once per frame
    void Update()
    {

    }
}

Tags: