Создание drag&drop инвентаря в Unity с использованием UI(C#). Часть 2
4. Создание слотов Теперь вернемся немного назад, туда где мы создавали слоты. Помните я говорил, что не следует заморачиваться с расположением слотов ? Создаем скрипт InventoryButtonCreate и вешаем его на Canvas. Ничего в нем изменять не будем, он нам нужен для создания Custom Editor. Далее создаем папку Editor(обратите внимание на название папки, с другим названием не пойдет). Примечание: Editor - зарезервированное наименование директории, предназначенной для доступа сценариев к Unity Editor Scripting API. Если Ваш скрипт использует какие либо классы или функции пространства имен UnityEditor, тогда для корректной работы он должен быть помещен в данную директорию. Создаем в папке Editor скрипт InventoryEditor. Пишим код:
Код
using UnityEngine; using System.Collections.Generic; using UnityEditor;
[CustomEditor(typeof(InventoryButtonCreate))] [CanEditMultipleObjects] public class InventoryEditor : Editor{
public GameObject go; public GameObject InventoryObj;
public int ColumnCount; public int RowCount; public int SlotSize;
go = EditorGUILayout.ObjectField("Слот ячейки", go, typeof(GameObject), true) as GameObject;
InventoryObj = EditorGUILayout.ObjectField("Инвентарь: ", InventoryObj, typeof(GameObject), true) as GameObject;
//создаем ячейки if (GUILayout.Button("Добавить ячейки")) { for (int k = 0; k < RowCount; k++) { for (int i = 0; i < ColumnCount; i++) { GameObject slot = Instantiate(go) as GameObject;
SetSize(go.GetComponent<RectTransform>(), new Vector2(SlotSize, SlotSize));
slot.GetComponent<RectTransform>().localPosition = new Vector2((slot.GetComponent<RectTransform>().rect.xMin + 50f) + (i * SlotSize), (slot.GetComponent<RectTransform>().rect.yMax - 30f) - (k * SlotSize));
Теперь смотрим в инспектор и у нас появились новые поля. Первое поле - размер ячейки Второе - кол-во колонок Третье - кол-во столбцов Четвертое - родитесльский обьект Пятое - обьект слота Указываем нужный размер ячейки(я поставил 40), кол-во колонок(я поставил 5) и столбцов(я поставил 7), в качестве родителя указываем панель Inventory, в поле слота перетаскиваем префаб слота. Нажимаем кнопку "Добавить ячейки". Ячейки создались
Выделяем их все и перетаскиваем на панель.
5. Сундук с лутом Теперь переходим к созданию сундука с лутом. Перетаскиваем префаб нашего слота на сцену изменяем его название на "ChestSlot" создаем из него новый префаб, удалив тот, что мы раньше перетащили на сцену. Создаем тег "ChestSlot" и присваиваем этот тег новому префабу. Далее вещаем скрипт LootChest на Canvas (если вы не сделали этого раньше). Открываем скрипт. Создаем константу типаstring в которой храним путь к изображению пустой ячейки. Так же вводим словарь, в котором будет храниться предмет с которым мы будет работать. Список ChestSlotsObj, где хранятся слоты инвентаря сундука.
Код
public const string DEFAULT_ICON = "slot";
public Dictionary<int , ItemDataBase> useItem = new Dictionary<int , ItemDataBase>();//вспомогательный словарь, где храним предмет инвентаря, над //которым производим действия (смотрим LootChestSlotEvent) public List<GameObject> ChestSlotsObj = new List<GameObject>(); //список хранящий в себе все слоты
public GameObject ChestPanel;//панель
Далее на сцене создаем два куба (это будут наши сундуки "_"). После создаем скрипт с именем LootChestCreate. Открываем... Создаем делегат принимающий параметр Dictionary<int , ItemDataBase>. Дальше создаем событие ClickChestevent c типом делегата ClickOnChest. Еще нам необходим словарь в котором будем хранить обьекты и приватная переменная типаbool.
Код
public delegate void ClickOnChest(Dictionary<int , ItemDataBase> item);
public static event ClickOnChest ClickChestevent;//события нажатия
private bool used;
private Dictionary<int , ItemDataBase> LootItem = new Dictionary<int , ItemDataBase>();//в словарь в котором храним добавленые предметы
Далее переходим обратно в скрипт LootChest. В нем создаем метод отвечающий за отображения свойств предмета. Подписываемся на этот метод
Код
using UnityEngine; using System.Collections.Generic; using UnityEngine.UI; using UnityEditor;
public class LootChest : MonoBehaviour {
public const string DEFAULT_ICON = "slot";
public Dictionary<int , ItemDataBase> useItem = new Dictionary<int , ItemDataBase>();//вспомогательный словарь, где храним предмет инвентаря, над //которым производим действия (смотрим LootChestSlotEvent) public List<GameObject> ChestSlotsObj = new List<GameObject>(); //список хранящий в себе все слоты
public GameObject ChestPanel;//панель
void Awake() { LootChestCreate.ClickChestevent += ChestSlotsCondition;//подписываемся на событие
}
void Update() { }
/// <summary> /// Показываем изображение, если там есть обьект инвентаря /// </summary> /// <param name="item">обьект</param> public void ChestSlotsCondition(Dictionary<int , ItemDataBase> item) { useItem = item;
ChestPanel.SetActive(true);
for (int i = 0 ; i < ChestSlotsObj.Count ; i++) { if (item.ContainsKey((i))) { ChestSlotsObj[(i)].GetComponent<Image>().sprite = Resources.Load<Sprite>(item[(i)].IconPatch); } else { ChestSlotsObj[(i)].GetComponent<Image>().sprite = Resources.Load<Sprite>(DEFAULT_ICON); } } } }
Возвращаемся в скрипт LootChestCreate и в методе OnMouseDown() (который срабатывает при нажатии мышкой на обьект) создаем предметы для инвентаря сундука
Код
using UnityEngine; using System.Collections.Generic;
/* * Скрипт активирующий окно сундука с лутом (вешать на обьект сундука) */
public class LootChestCreate : MonoBehaviour {
public delegate void ClickOnChest(Dictionary<int , ItemDataBase> item);
public static event ClickOnChest ClickChestevent;//события нажатия
private bool used;
private Dictionary<int , ItemDataBase> LootItem = new Dictionary<int , ItemDataBase>();//в словарь в котором храним добавленые предметы
void OnMouseDown() { if (!used) { //добавляем предметы в сундук (для теста) LootItem.Add(0 , ItemGenerator._ItemGenerator.ItemGen(Random.Range(0 , ItemGenerator._ItemGenerator.ItemList.Count))); LootItem.Add(6 , ItemGenerator._ItemGenerator.ItemGen(Random.Range(0 , ItemGenerator._ItemGenerator.ItemList.Count)));
used = true; } //запускаем событие if (ClickChestevent != null) ClickChestevent.Invoke(LootItem); else Debug.LogError("События создания интерфейса сундука с лутоп ПУСТОЕ"); } }
Теперь вешаем скрипт LootChestCreate на наши кубы-сундуки.
Создаем скрипт с именем LootChestSlotEvent и вешаем его на префаб ChestSlot. И пишем код.
Код
using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSystems;
/* * Скрипт реализующий перемещение предметов * внутри сундука с лутом(вешать на обьект ячейки) */
public class LootChestSlotEvent : MonoBehaviour , IPointerClickHandler , IDragHandler , IPointerEnterHandler , IPointerExitHandler , IEndDragHandler , IDropHandler { public int SlotNumber;//номер ячейки private bool click;
//Нажатие мышки по ячейке public void OnPointerClick(PointerEventData eventData) { if (GameObject.FindGameObjectWithTag("Canvas").GetComponent<LootChest>().useItem.ContainsKey(SlotNumber)) Debug.Log(GameObject.FindGameObjectWithTag("Canvas").GetComponent<LootChest>().useItem[SlotNumber].Name);
}
//Начало перемещения ячейки (движение при зажатой ЛКМ) public void OnDrag(PointerEventData eventData) { if (GameObject.FindGameObjectWithTag("Canvas").GetComponent<LootChest>().useItem.ContainsKey(SlotNumber)) { inventory.DragObject(GameObject.FindGameObjectWithTag("Canvas").GetComponent<LootChest>().useItem[SlotNumber]); GameObject.FindGameObjectWithTag("Canvas").GetComponent<LootChest>().useItem.Remove(SlotNumber); inventory.ConditionSlots(SlotNumber , true , "chest"); } }
//Курсор над ячейкоц public void OnPointerEnter(PointerEventData eventData) { if (!PlayerGeneralSetting._Inventory.ContainsKey(SlotNumber)) { click = true; } }
//Курсор НЕ над ячейкой public void OnPointerExit(PointerEventData eventData) { if (!PlayerGeneralSetting._Inventory.ContainsKey(SlotNumber)) { click = false; } }
Как видите код практически идентичен коду в скрипте SlotEvent.
Теперь необходимо создать панель с инвентарем сундука и слоты. Создаем Panel и называем ее Chest. Слоты создаем точно так же, как и слоты для инвентаря. В скрипте InventoryButtonCreate указываем размер ячеек, количество ячеек, в поле "Слот ячейки" перетаскиваем префаб ChestSlot, в поле "Инвентарь" помещаем панель Chest, нажимаем кнопку "Создать ячейки".
Возвращаемся в скрипт LootChest и дописываем код. В испекторе перетаскиваем в поле ChestPanel нашу панель Chest. А в поле - список ChestSlotsObj наши слоты сундука.
Код
using UnityEngine; using System.Collections.Generic; using UnityEngine.UI; using UnityEditor;
/* * Создание сундука с предметами * (Внешний вид) */
public class LootChest : MonoBehaviour {
public const string DEFAULT_ICON = "slot";
public Dictionary<int , ItemDataBase> useItem = new Dictionary<int , ItemDataBase>();//вспомогательный словарь, где храним предмет инвентаря, над //которым производим действия (смотрим LootChestSlotEvent) public List<GameObject> ChestSlotsObj = new List<GameObject>(); //список хранящий в себе все слоты
public GameObject ChestPanel;//панель
void Awake() { LootChestCreate.ClickChestevent += ChestSlotsCondition;//подписываемся на событие
int a = 0;//вспомогательная переменная
for (int i = 0 ; i < ChestSlotsObj.Count ; i++) { ChestSlotsObj[i].GetComponentInChildren<Text>().text = i.ToString();//нумирация слотов
ChestSlotsObj[i].GetComponent<LootChestSlotEvent>().SlotNumber = a;//пердаем номер слота скрипту LootChestSlotEvent
a++; }
ChestPanel.SetActive(false);//выключаем окно }
void Update() { }
/// <summary> /// Показываем изображение, если там есть обьект инвентаря /// </summary> /// <param name="item">обьект</param> public void ChestSlotsCondition(Dictionary<int , ItemDataBase> item) { useItem = item;
ChestPanel.SetActive(true);
for (int i = 0 ; i < ChestSlotsObj.Count ; i++) { if (item.ContainsKey((i))) { ChestSlotsObj[(i)].GetComponent<Image>().sprite = Resources.Load<Sprite>(item[(i)].IconPatch); } else { ChestSlotsObj[(i)].GetComponent<Image>().sprite = Resources.Load<Sprite>(DEFAULT_ICON); } } }
//Очищаем инвентарь сундука public void СlearInventory() { ChestPanel.SetActive(false); }
/// <summary> /// Изменяем изображение иконки ячейки при добавление предмета в нее /// </summary> /// <param name="key">номер ячейки</param> public void ChangeSlotIcon(int key) { if (useItem.ContainsKey((key))) { ChestSlotsObj[(key)].GetComponent<Image>().sprite = Resources.Load<Sprite>(useItem[(key)].IconPatch); } else { ChestSlotsObj[(key)].GetComponent<Image>().sprite = Resources.Load<Sprite>(DEFAULT_ICON); } }
}
На этом собственно все. Как я уже писал выше статья большая и возможно я мог где то оишбиться в коде или последовательности действий, поэтому смотрим исходник Исходниктык Все скрипты тык Первая часть статьи
Категория: Создание игр | Добавил: beril (03 Января 2015)
| Автор: Шевченко Денис
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Создание drag&drop инвентаря в Unity с использованием UI(C#). Часть 2», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.