← Назад к вопросам

Как по ключу найти значение?

2.0 Middle🔥 251 комментариев
#Коллекции и структуры данных

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Поиск значения по ключу в Unity (C#)

В контексте разработки на Unity с использованием C#, поиск значения по ключу — это фундаментальная операция, которая чаще всего выполняется с использованием коллекций, реализующих интерфейс IDictionary<TKey, TValue>. В Unity мы работаем в основном с C#, поэтому рассмотрим основные подходы.

Основные коллекции для хранения пар "ключ-значение"

В C# для этой цели используются несколько структур данных:

  1. Dictionary<TKey, TValue> — наиболее распространённая и эффективная хеш-таблица. Обеспечивает очень быстрый поиск (близкий к O(1)) по уникальному ключу.
  2. Hashtable — устаревшая необобщённая версия словаря (из пространства имён System.Collections). В новых проектах рекомендуется использовать Dictionary.
  3. SortedDictionary<TKey, TValue> — словарь, в котором элементы автоматически сортируются по ключу.
  4. PlayerPrefs — специализированный механизм Unity для сохранения простых данных пользователя (int, float, string) между сессиями. Использует строковый ключ.

Практические примеры в коде

1. Использование Dictionary<ТKey, TValue>

Это самый частый сценарий в игровой логике: хранение характеристик предметов, конфигураций, ссылок на префабы и т.д.

using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    // Объявляем словарь, где ключ - строка (ID предмета), значение - структура с данными
    private Dictionary<string, ItemData> _itemDictionary = new Dictionary<string, ItemData>();

    [System.Serializable]
    public struct ItemData
    {
        public string displayName;
        public int value;
        public Sprite icon;
    }

    void Start()
    {
        // Инициализируем словарь данными
        _itemDictionary.Add("sword_01", new ItemData { displayName = "Железный меч", value = 50 });
        _itemDictionary.Add("potion_health", new ItemData { displayName = "Зелье здоровья", value = 20 });

        // ПОИСК ЗНАЧЕНИЯ ПО КЛЮЧУ:
        // Способ 1: Попытка получить значение (самый безопасный и рекомендуемый способ)
        string keyToFind = "potion_health";
        if (_itemDictionary.TryGetValue(keyToFind, out ItemData foundItem))
        {
            // Если ключ существует, переменная foundItem теперь содержит данные
            Debug.Log($"Найдено: {foundItem.displayName}, цена: {foundItem.value}");
        }
        else
        {
            Debug.LogWarning($"Предмет с ключом '{keyToFind}' не найден в базе данных.");
        }

        // Способ 2: Прямое обращение по ключу (выбросит исключение, если ключа нет)
        // ItemData riskyItem = _itemDictionary["sword_01"]; // Работает
        // ItemData brokenItem = _itemDictionary["non_existent_key"]; // Выбросит KeyNotFoundException!

        // Способ 3: Проверка существования ключа перед обращением
        if (_itemDictionary.ContainsKey("sword_01"))
        {
            ItemData safeItem = _itemDictionary["sword_01"];
        }
    }
}

2. Использование PlayerPrefs

PlayerPrefs — это не коллекция в памяти, а интерфейс для работы с постоянным хранилищем (реестром на Windows, plist на macOS).

using UnityEngine;

public class SaveManager : MonoBehaviour
{
    void Start()
    {
        // Сохраняем значение по ключу
        PlayerPrefs.SetInt("PlayerScore", 1250);
        PlayerPrefs.SetString("PlayerName", "Hero");
        PlayerPrefs.Save(); // Важно: данные записываются на диск

        // ПОИСК (ЗАГРУЗКА) ЗНАЧЕНИЯ ПО КЛЮЧУ:
        // Второй параметр - значение по умолчанию, если ключ не найден
        int loadedScore = PlayerPrefs.GetInt("PlayerScore", 0);
        string loadedName = PlayerPrefs.GetString("PlayerName", "Unknown");

        Debug.Log($"Игрок: {loadedName}, Счёт: {loadedScore}");

        // Проверка существования ключа
        if (PlayerPrefs.HasKey("PlayerScore"))
        {
            // Ключ существует
        }
    }
}

Критические моменты и лучшие практики

  • Всегда используйте TryGetValue() для Dictionary: Это предотвращает исключения KeyNotFoundException и является более производительным, чем комбинация ContainsKey + индексатор, так как поиск выполняется один раз.
  • Уникальность ключей: В Dictionary ключи должны быть уникальными. Попытка добавить существующий ключ вызовет ArgumentException.
  • Производительность: Dictionary основан на хеш-кодах ключей. Для пользовательских типов в качестве ключа необходимо корректно реализовать методы GetHashCode() и Equals().
  • Потокобезопасность: Стандартный Dictionary не является потокобезопасным. Для многопоточных операций используйте ConcurrentDictionary (из System.Collections.Concurrent) или механизмы синхронизации.
  • PlayerPrefs для простых данных: Не используйте PlayerPrefs для больших объёмов данных или сложных структур. Для этого есть бинарная сериализация, JSON (например, JsonUtility), ScriptableObject или специализированные решения для сохранения.

Выбор метода зависит от задачи: для быстрого доступа к данным во время выполнения игры используйте Dictionary; для постоянного хранения настроек или прогресса между запусками — PlayerPrefs или систему сериализации. Понимание этих механизмов — основа эффективной работы с данными в Unity.