Инвентарь, отображение информации об объекте на Unity.

Важной составляющей инвентаря является возможность посмотреть всю доступную информацию об объекте. В какой-то степени это позволяет улучшить gameplay игры. Так, например, если у вещи доступен просмотр описания, можно погрузить игрока в историю, которая открывает какой-либо квест в игре. Это и касается других характеристик вещи.

Перед тем, как перейти к созданию отображения информации об объекте, я бы посоветовал вам ознакомиться с предыдущими статьями о создании инвентаря: «Улучшаем инвентарь, перемещением по нажатию на Unity» и «Создание простого инвентаря в игре на Unity» [ссылка на статью].

Отображение информации - окно с информацией

Настраиваем сцену.

Для того, чтобы реализовать отображение информации об объекте, для начала необходимо создать окно, которое отображает информацию об этом самом объекте.

Моё окно отображения выглядит следующим образом:

Отображение информации - Создание окна с информацией

В окне отображения присутствует следующие компоненты:

  • Cell – ячейка, которая содержит иконку объекта;
  • Name – наименование объекта;
  • Level_circle – уровень и количество очков объекта;
  • Layout – слой, содержащий в себе описание объекта, а так же место, для списка характеристик;
  • SellMarket – кнопка для продажи вещи на рынке;
  • Sell – кнопка для продажи вещи;
  • PutOn – кнопка для того, чтобы одеть вещь на игрока;
  • Close – кнопка, для того, чтобы закрыть данное окно;

Когда ваше окно будет создано, можно переходить к написанию скриптов.

Пишем скрипты управления окном отображения информации об объекте.

Сразу хотелось бы отметить, что в качестве примера будет использоваться инвентарь от проекта DarkCaves.

И так, в первую очередь хотелось бы показать вам все переменные, которые отвечают за какую-либо информацию об объекте (вещи).

// тип объекта 

public enum Type {
    armor, // броня 
    weapon, // оружие  
    amulet, // амулет   
    ring // кольцо } // класс объекта
    public enum Class {
    standard, // стандартный   
    special, // специальный   
    rare, // раритетный   
    individual // индивидуальный 
}
[System.Serializable]
public class Item {
    public int id = 0; // идентикафиционный номер     
    public Type type; // тип вещи  
    public Class @class; // клас вещи  
    [Header("Информация")]
    public string name = ""; // наименование вещи 
    public string description = ""; // описание вещи   
    [Header("Характеристики")]
    public int level = 1; // уровень вещи  
    public int glasses = 0; // очки вещи 
    public int magArmor = 0; // магическая защита 
    public int damArmor = 0; // физическая защита   
    public int damage = 0; // урон   
    public int health = 0; // жизни  
    [Header("Зачарование")]
    public int spellMagArmor = 0; // процент зачарования магической защиты 
    public int spellDamArmor = 0; // процент зачарования физической защиты   
    public int spellReverseDamage = 0; // процент зачарования обратного урона   
    public int spellVampirism = 0; // процент зачарования вампиризма от нанесённого урона 
    public int spellCriticalDamage = 0; // процент нанесения критического урона   
    [Header("Объекты")]
    public RectTransform gameObject; // объект на сцене  
    public Texture2D image; // текстура объекта 
}

Характеристики, которые я буду отображать:

  • Тип вещи;
  • Класс вещи;
  • Наименование вещи;
  • Описание;
  • Уровень;
  • Очки;
  • Магическая защита;
  • Физическая защита;
  • Урон;
  • Жизни.

Метод, который будет отображать данные характеристики необходимо вынести в отдельный скрипт, который называется InfoManager и висит на самом объекте.

Отображение информации - Настройка окна с информацией

Переменные данного скрипта:

public GameObject infoItem; // объект отображения информации об объекте (объект, который выключается при закрытии) 
public Transform RectTransformParrent; // родитель для объектов характеристик, отображающихся списком 
public GameObject itemObject; // ячейка в списке характеристик 
[Space(5)]
public Text nameItem; // текст для отображения наименования об объекте 
public Text desriptionItem; // текст для отображения описания об объекте 
public Text level; // текст для отображения левела объекта 
[Space(5)]
public RawImage icon; // объект для отображения иконки вещи 
public Image imageGlasses; // объект для отображения очков вещи 
[Space(5)]
public List levels = new List(50); // список левелов 

Функции скрипта:

void Awake()
{
    // просчитываем очки для левелов   
    for (int i = 1; i < 50; i++)
    {
        levels[i] = levels[i - 1] + (i + 1) * 10;
    }
} /// /// Функция для указания информации ///  
  ///вся информация о вещи 
public void SelectInformation(Item item)
{
    nameItem.text = item.name; // указываем наименование вещи  
    desriptionItem.text = item.description; // указываем описание вещи  
    icon.texture = item.image; // указываем изображение вещи
                               // указываем очки вещи   
    if (item.level > 0 && item.level < 51)
    {
        // если уровень больше нуля и меньше 50   
        float glasses = (float)item.glasses; // указываем количество очков вещи   
        float maxGlasses = (float)levels[item.level]; // указываем максимальное количество очков   
        if (item.level > 1) // если уровень больше одного    
        {
            glasses -= (float)levels[item.level - 1]; // перерасчитвыаем очки вещи    
            maxGlasses -= (float)levels[item.level - 1]; // перерасчитываем максимальные очки вещи     
        }
        imageGlasses.fillAmount = glasses / maxGlasses; // указываем очки вещи   
    }
    level.text = item.level.ToString(); // указываем левел вещи 
                                        // переменная для расчётов    
    int y = -110; // -90 - высота на которой создаётся вторая ячейка  
    // выводим характеристики 
    GameObject itemClass = (GameObject)Instantiate(itemObject, RectTransformParrent, false); // создаём объект, отображающий класс вещи 
    itemClass.GetComponent().SelectInfo([email protected], [email protected]()); // вызываем функцию заполнения информации 
    if (item.health != 0)
    {
        // если объект добавляет жизни    
        GameObject itemHealth = (GameObject)Instantiate(itemObject, RectTransformParrent, false); // создаём объект, отображающий жизни объекта   
        itemHealth.GetComponent().SelectInfo(ItemManager.type.health, item.health.ToString()); // вызываем функцию заполнения информации  
        itemHealth.GetComponent().anchoredPosition = new Vector2(itemHealth.GetComponent().anchoredPosition.x, y); // сдвигаем объект на строчку вниз  
        y -= 80;
        // 80 - ширина ячейки + отступ   
    }
    if (item.damage != 0)
    {
        // если объект добавляет здоровье     
        GameObject itemDamage = (GameObject)Instantiate(itemObject, RectTransformParrent, false); // создаём объект, отображающий урон объекта   
        itemDamage.GetComponent().SelectInfo(ItemManager.type.damage, item.damage.ToString()); // вызываем функцию заполнения информации     
        itemDamage.GetComponent().anchoredPosition = new Vector2(itemDamage.GetComponent().anchoredPosition.x, y); // сдвигаем объект на строчку вниз   
        y -= 80; // 80 - ширина ячейки + отступ
    }
    if (item.magArmor != 0)
    {
        // если объект добавляет магическую броню      
        GameObject itemMagArmor = (GameObject)Instantiate(itemObject, RectTransformParrent, false); // создаём объект, отображающий магическую броню объекта   
        itemMagArmor.GetComponent().SelectInfo(ItemManager.type.magArmor, item.magArmor.ToString());  // вызываем функцию заполнения информации      
        itemMagArmor.GetComponent().anchoredPosition = new Vector2(itemMagArmor.GetComponent().anchoredPosition.x, y); // сдвигаем объект на строчку вниз    
        y -= 80; // 80 - ширина ячейки + отступ 
    }
    if (item.damArmor != 0)
    {
        GameObject itemDamArmor = (GameObject)Instantiate(itemObject, RectTransformParrent, false); // создаём объект, отображающий физическую броню объекта   
        itemDamArmor.GetComponent().SelectInfo(ItemManager.type.damArmor, item.damArmor.ToString());  // вызываем функцию заполнения информации   
        itemDamArmor.GetComponent().anchoredPosition = new Vector2(itemDamArmor.GetComponent().anchoredPosition.x, y); // сдвигаем объект на строчку вниз     
        y -= 80; // 80 - ширина ячейки + отступ   
    }
    // добавлять отображение остальнах характеристик 
} /// /// функция закрытия окна с отображением характеристик объекта ///  
public void Close()
{
    // удаляем старые характеристики объекта    
    for (int i = 0; i < RectTransformParrent.childCount; i++)
        Destroy(RectTransformParrent.GetChild(i).gameObject);
    // закрываем окно    
    infoItem.SetActive(false);
}

Данный скрипт имеет три функции. Первая функция – Awake() предназначена для просчитывания максимальных очков для каждого уровня вещи.

Функция — SelectInformation() выполняют основную функцию скрипта – заполняет текстовые поля для информации, информацией об объекте. Для начала заполняется вся статическая информация, которая существует у каждого объекта, а после происходит заполнение динамической информации – жизни, магическая защита, физическая защита, урон.

Следующий скрипт, который необходимо создать, будет отвечать за заполнения характеристик в динамической ячейке. Все динамические ячейки будут создаваться в отдельном столбце.

Отображение информации - Настройка характеристик объекта

Вам необходимо создать, объект, который будет иметь следующие параметры:

  • Иконку (icon)
  • Наименование характеристики (Text)
  • Значение характеристики (value)

Этот объект необходимо сохранить в префаб и в последующем указать для скрипта InfoManager.

Отображение информации - Создание характеристик

Создадим скрипт ItemManager и добавим его на объект item.

Текст скрипта:

// тип характеристики 
public enum type
{
    @class, // класс    
    health, // здоровье  
    magArmor, // магическая защита   
    damArmor, // физическая защита    
    damage // урон 
}
public Image icon; // иконка 
public Text name; // наименование 
public Text value; // значение 
[Header("Иконки")]
public Sprite ic_class; // иконка класса 
public Sprite ic_health; // иконка здоровья 
public Sprite ic_magArmor; // иконка магической защиты 
public Sprite ic_damArmor; // иконка физической защиты 
public Sprite ic_damage; // иконка урона ///
/// функция заполнения информации /// 
/// ///тип характерисики ///значение характеристики 
public void SelectInfo(type types, string values)
{
    /// // проверяем какой тип динамической характерисики   
    switch (types)
    {
        // если тип характеристики класс         
        case [email protected]:
            name.text = "Class item:"; // указываем наименование    
                                       // в зависимости от наименования указываем цвет значения         
            if (values == "standard")
            {
                value.color = new Color(1, 1, 0);
            }
            else if (values == "special")
            {
                value.color = new Color(1, 0.5f, 0);
            }
            else if (values == "rare")
            {
                value.color = new Color(1, 0, 0);
            }
            else if (values == "individual")
            {
                value.color = new Color(1, 0, 1);
            }
            icon.sprite = ic_class; // указываем иконку      
            break;
        // если тип здоровье         
        case type.health:
            icon.sprite = ic_health; // указываем иконку    
            name.text = "Health:"; // указываем наименование     
            break;         // если тип магическая защита    
        case type.magArmor:
            icon.sprite = ic_magArmor; // указываем иконку      
            name.text = "Magic armor:"; // указываем наименование    
            break;         // если тип физическая защита      
        case type.damArmor:
            icon.sprite = ic_damArmor; // указываем иконку     
            name.text = "Physical armor:"; // указываем наименование      
            break;         // если тип урон    
        case type.damage:
            icon.sprite = ic_damage; // указываем иконку    
            name.text = "Damage:"; // указываем наименование   
            break;
    }
    value.text = values; // указываем значение 
}

Осталось только дописать основной скрипт, который управляет инвентарём. Переходим к редактированию InventoryManager.

Здесь у нас появился новый метод, отвечающий за открытие окна с информацией об объекте:

/// /// Открытие окна информации об объекте ///  ///Идентификатор объекта в списке 
void OpenItemInformation(int id) {
    ItemInfo.SetActive(true); // показываем окно информации об объекта   
    infoManager.SelectInformation(items[id]); // обновляем информацию об объекта 
} 

Так же добавились две новые переменные:

public InfoManager infoManager; // скрипт управления окном информации public GameObject ItemInfo; // окно информации 

И самая главная функция, отвечающая за полную работу инвентаря, функция Update(). В данной функции открытие инвентаря настроено на двойное нажатие по объекту.

void Update()
{
    if (Input.GetKeyDown(KeyCode.Mouse0))
    {
        if (activeCell != -1 && items[activeCell].gameObject != null)
        {
            oldActiveCell = activeCell;
            OldPositionMouse = Input.mousePosition; // запоминаем координаты мыши         
        }
    }
    if (Input.GetKey(KeyCode.Mouse0))
    {
        if (oldActiveCell != -1)
        {
            if (Vector2.Distance(OldPositionMouse, Input.mousePosition) > 10)
            { // если дистанция перемещения больше 10        
                items[oldActiveCell].gameObject.parent = canvas; // меняем родителя для объекта вещи             
                float x = Input.mousePosition.x / Screen.width * canvas.sizeDelta.x; // расчитвываем координаты мыши         
                float y = Input.mousePosition.y / Screen.height * canvas.sizeDelta.y; // расчитвываем координаты мыши            
                items[oldActiveCell].gameObject.anchoredPosition = new Vector2(x, y); // перемещаем объект       
            }
        }
    }
    if (Input.GetKeyUp(KeyCode.Mouse0))
    {
        if (activeCell != -1)
        {
            // если мы навели на ячейку           
            if (items[activeCell].gameObject == null)
            {
                // если объекта в ячейке не существует         
                if (oldActiveCell != -1) { ChangeItem(activeCell, oldActiveCell); ResetItem(activeCell); }
                else
                {
                    // если мы не перемещали до этого вещь          
                    if (activeCellClick != -1)
                    {
                        // если у нас выделена какая-то вещь                
                        ChangeItem(activeCell, activeCellClick); // меняем вещи местами          
                        ResetItem(activeCell); // перемещаем объект вещи на новую позицию         
                        cells[activeCellClick].GetComponent().enabled = false; // отключаем обводку           
                        activeCellClick = -1; // удаляем сохранение выделенной вещи               
                    }
                }
            }
            else
            {
                // если в ячейке существует объект                
                if (oldActiveCell != -1)
                {
                    if (activeCell == oldActiveCell)
                    {
                        if (activeCellClick == -1)
                        {
                            // проверка на нажатие                 
                            if (Vector2.Distance(OldPositionMouse, Input.mousePosition) < 10)
                            { // если дистанция перемещения меньше 10       
                                cells[activeCell].GetComponent().enabled = true; // выделяем ячейку                              
                                activeCellClick = activeCell; // запоминаем выделенную ячейку                       
                            }
                        }
                        else
                        {
                            if (activeCellClick == activeCell)
                            { // если старое нажатие произошло на тот-же самый объект        
                                OpenItemInformation(activeCellClick); // открываем информацию об объекте                      
                            }                               // дописать смену местами                    
                            cells[activeCellClick].GetComponent().enabled = false; activeCellClick = -1;
                        }
                    }
                    ResetItem(oldActiveCell);
                }
            }
        }
        else
        {
            // если мы не навели на ячейку          
            if (oldActiveCell != -1) { ResetItem(oldActiveCell); }
        }
        oldActiveCell = -1;
    }
}

Ну и на этом всё, осталось только настроить сцену.

Настройка сцены.

Для начала необходимо настроить скрипт InfoManager, отвечающий за заполнение информации об объекте. Указываем все поля.

Отображение информации - Заполнение переменных окна с информацией

Так же, для клавиши закрытия окна, необходимо указать функцию в скрипте:

Отображение информации - Настройка выхода

После чего переходим к настройке динамической ячейки. Здесь так же, необходимо указать все поля.

Отображение информации - Заполнение переменных характеристик

Осталось только настроить InventoryManager следующим образом:

  • В переменную infoManager нужно указать скрипт, который у меня находится на объекте с информацией;
  • А в переменную ItemInfo, необходимо указать сам объект информации.
Отображение информации - Настройка инвентаря

На этом всё. Если вы всё правильно сделали, то при двойном нажатии на вещь у вас будет открываться информация об объекте.

Автор статьи: Александр Каримов

Пока нет оценок, но вы можете быть первым!

Оцените