Владимир Шека 4 Share Posted May 29, 2018 Для начала посмотрите видеоуроки от Stream: https://www.youtube.com/watch?v=Y-OpWcRhgJ0 - полностью https://www.youtube.com/watch?v=wgl69JPczG0 - до 28 минуты (дальше не делал, и мой скрипт дальше не развивался, там идет про то, как брать предметы в руку) Теперь, если хотите лучше понять, как это работает, то посмотрите мое видео: Новичку без просмотра видео по Unity-инвентарю от Steam'а будет почти невозможно разобраться. Мое видео в качестве бонуса детальней разжевывает, как работает алгоритм, плюс в моих скриптах добавлены комментарии. Пару замечаний: в своем втором видео Stream переименовал в cell префаб, который в первом видео называл Panel картинки-спрайты для отображения в инвентаре необходимо сделать в инспекторе Sprite (2D and UI) А теперь мои скрипты и префабы (единственное отличие у меня предметы берутся не райкастами по клику мыши, а подбираются при соприкосновении ими через коллайдер игрока). Чтобы не вносить путаницу я не стал изменять скрипт после записи своего видео, если нужно можете самостоятельно переименовать названия переменных в более логичные. В архиве скрипты на инвентарь Inventory, Item, Drag, Drop, пару префабов (куб, сфера), иконки для префабов, и в качестве бонуса префаб CanvasInvetory: скачать AssetsInventoryStream.rar или с Яндекс Диска https://yadi.sk/d/Ynpn7bfj3WfZr8 Что делать с этими скриптами смотрите в видео Стрима Тексты скриптов на инвентарь (превью): Inventory.cs Спойлер using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; public class Inventory : MonoBehaviour { //Сделано по уроку https://www.youtube.com/watch?v=Y-OpWcRhgJ0 и https://www.youtube.com/watch?v=wgl69JPczG0 List<Item> list; //список для хранения вещей в инвентаре public GameObject inventory; //панель из канваса, содержащая отображение инвентаря public GameObject container; //слот в инвентаре (панели канваса) //public Living controller; //получаем скрипт игрока (в данном случае только чтобы хп регнуть ему в use), ЗАМЕНИТЕ Living на название своего скрипта //весящего на игроке, и в котором есть функция хп регена void Start() { list = new List<Item>(); //инициализируем лист (массив) инвентаря //controller = GetComponent<Living>(); //РАСКОМЕНТИРУЙТЕ, КОГДА ОПРЕДЕЛИТЕ СВОЙ СКРИПТ ВМЕСТО public Living controller; } void OnCollisionEnter(Collision collision) //вещи подбираются по соприкосновению игрока с ними (для работы необходимо, чтобы на GameObject'е, на котором //висит этот скрипт, также был и коллайдер { if (list.Count < inventory.transform.childCount) //чтобы нельзя было взять в инвентарь больше предметов, чем слотов в визуальном инвентаре { Item item = collision.collider.GetComponent<Item>(); //помещаем в переменную item объект, с которым столкнулись (поместится если он содержит скрипт Item) if (item != null) //проверяем что в этой переменной что-то есть на случай, если объект не был Item { list.Add(item); //помещаем в наш список-инвентарь вещь, с которой столкнулись Destroy(collision.collider.gameObject); //удаляем вещь со сцены } } } void Update() { //получение предмета по райкасту отключено, почему-то не работает, использую on collision enter //if (Input.GetMouseButtonUp(0)) //{ // Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // RaycastHit hit; // if (Physics.Raycast(ray, out hit)) // { // Item item = hit.collider.GetComponent<Item>(); // if (item != null) // { // list.Add(item); // Destroy(hit.collider.gameObject); // } // } //} if (Input.GetKeyDown(KeyCode.I)) //при нажатии кнопки { if (inventory.activeSelf) //если инвентарь активен { inventory.SetActive(false); //делаем неактивным инвентарь for (int i = 0; i < inventory.transform.childCount; i++) //пробегаемся по всем ячейкам инвентаря (пока i меньше, чем "детей"(ячеек) у панели с инвентарем) { if (inventory.transform.GetChild(i).transform.childCount > 0) //если в ячейке количество детей больше 0 (т.е. если в ней что-то лежит) { Destroy(inventory.transform.GetChild(i).transform.GetChild(0).gameObject); //удаляем то, что лежит в ячейке (удаляется только картинка //из инвентаря. Из самого списка инвентаря не удаляется. } } } else //иначе (если инвентарь неактивен) { inventory.SetActive(true); //активируем инвентарь //int count = list.Count; //создаем переменную, в которой будет число количества предметов в инвентаре (не путаться с количеством слотов всего) for (int i = 0; i < list.Count; i++) //пробегаемся по всем предметам, которые есть в списке инвентаря { Item it = list[i]; //создаем переменную типа подбираемого предмета, и помещаем в нее элемент списка под номером i if (inventory.transform.childCount >= i) //если количество слотов в канвасе больше или равно количеству предметов в инвентаре, то выводим предметы //на экран. Если слотов меньше, чем предметов, то остальные предметы отображать не будем (else break;) { GameObject img = Instantiate(container); //создаем картинку под отображение конкретного предмета в инвентаре из префаба container //(на нем висит drag.cs) img.transform.SetParent(inventory.transform.GetChild(i).transform); //делаем картинку дочерней от слота в инвентаре img.GetComponent<Image>().sprite = Resources.Load<Sprite>(it.sprite); //устанавливаем картинке изображение той вещи, которая там должна лежать, //"Resources.Load<Sprite>" указывает, что нужно из Resouces загрузить файл типа "спайт", а (it.sprite) это путь, где мы писали адрес иконки в скрипте /*img.AddComponent<Button>().onClick.AddListener(() => remove(it, img));*/ //делаем панельку-слот кнопкой, которая вызывает фукнцию "выкинуть" img.GetComponent<Drag>().item = it; //в контейнера-картинки передаем скрипту drag.cs сам предмет, //который есть в инвентаре, в переменную item; } else break; //если предметов в визуальном инвентаре больше, чем слотов в списке инвентаря, то прерываемся на том предмете, который больше слотов } } } } /*void remove(Item it, GameObject obj)*/ //функция, выкидывающая вещь из инвентаря (вызывается кликом на вещи) void remove(Drag drag) //функция, выкидывающая вещь из инвентаря (вызывается кликом на вещи) { Item it = drag.item; GameObject newo = Instantiate<GameObject>(Resources.Load<GameObject>(it.prefab)); //создает объект в игровом миру, префаб объекта берет из переменной //.prefab в объекте it, который мы передали в эту функцию newo.transform.position = transform.position + transform.forward + transform.up; //задаем позицию создаваемого объекта в 1 метр вперед и 1 вверх //Destroy(obj); Destroy(drag.gameObject); //удаляет из инвентаря картинку (контейнер) предмета list.Remove(it); //удаляет полученный предмет из списка инвентаря } void use(Drag drag) //использование предмета. Вызывается из Drag.cs через "player.BroadcastMessage("use", this);" { if (drag.item.type == "food") //если тип предмета food (задается в префабе) { Item it = drag.item; //добываем из полученной переменной тип Item //controller.HPChange(25); //прибавляем хп игроку УКАЖИТЕ НАЗВАНИЕ СВОЕЙ ФУНКЦИИ, КОТОРАЯ РЕГАЕТ ХП В ВАШЕМ СКРИПТЕ ИГРОКА И РАСКОМЕНТИРУЙТЕ, КОГДА ОПРЕДЕЛИТЕ СВОЙ СКРИПТ ВМЕСТО public Living controller; Destroy(drag.gameObject); //удаляем из инвентаря картинку предмета list.Remove(it); //удаляем из списка инвентаря сам предмет } } } Item.cs Спойлер using System.Collections; using System.Collections.Generic; using UnityEngine; public class Item : MonoBehaviour { //этот скрипт вешается на все предметы, которые необходимо сделать подбираемыми public string type; //тип предмета public string sprite; //картинка предмета для инвентаря public string prefab; //префаб 3д объекта предмета для отображения в мире } Drag.cs Спойлер using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class Drag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler { //скрипт висит на префабе container, то есть на фигне, которая будет в инвентаре содержать картинку //конкретного предмета и символизировать именно его. Нужен скрипт, чтобы эти картинки можно было перетастиквать //также скрипт отправляет сообщения инвентарю (Inventory.cs), когда на предмет кликнули (чтобы использовать или выбросить) public Transform canvas; //ссылка на канвас, где хранится панель с инвентарем, идется в Start по тегу public Transform old; private GameObject player; //для получения игрока, ищется по тегу в Start public Item item; //переменная, принимающая из скрипта инвентаря конкретный итем при открытии инвентаря void Start() { canvas = GameObject.Find("CanvasInventory").transform; //ищем канвас, в котором находится наш инвентарь player = GameObject.FindGameObjectWithTag("Player"); //ищем объект с тегом Player } public void OnBeginDrag(PointerEventData eventData) //по началу перетаскивания { old = transform.parent; //в переменную записываем свое старое (текущее) положение, чтобы другие предметы могли занять это место, если мы перетащим //этот предмет на их место transform.SetParent(canvas); //в момент начала перетаскивания делаем родителя предмету канвас GetComponent<CanvasGroup>().blocksRaycasts = false; //отключаем ловлю райкаста контейнером в момент перетаскивания, чтобы ячейки ловили курсор //т.е. контейнер теперь через себя будет пропускать райкаст, пока перетаскивается } public void OnDrag(PointerEventData eventData) //в процессе перетаскивания { transform.position = Input.mousePosition; //меняем положение предмета в зависимости от положения мышки } public void OnEndDrag(PointerEventData eventData) //по завершению перетастиквания { GetComponent<CanvasGroup>().blocksRaycasts = true; //включаем ловлю райкаста контейнером, чтобы его опять можно было перетаскивать if (transform.parent == canvas) //если родитель это канвас { transform.SetParent(old); //тогда устанавливаем родителя того, кто был изначально до перетаскивания (хз зачем надо, может чтобы предмет возвращался //если мы его утащили куда-то не туда } } public void OnPointerClick(PointerEventData eventData) //когда мы кликнули по предмету в инвентаре { if (eventData.button == PointerEventData.InputButton.Left) //если клик левой кнопкой мыши { player.BroadcastMessage("use", this); //посылаем сообщение игроку(найденному по тегу), вызывая функцию use (может быть в любом скрипте на игроке) и передаем туда //этот объект (т.е. предмет из инвентаря) } else player.BroadcastMessage("remove", this); //если клик любой кнопкой кроме левой, то вызываем функцию remove } } Drop.cs Спойлер using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class Drop : MonoBehaviour, IDropHandler { //скрипт висит на слотах (панелях или ячейках) инвентаря public void OnDrop(PointerEventData eventData) //принимает объекты, которые перетянули на него мышкой и бросили { Drag drag = eventData.pointerDrag.GetComponent<Drag>(); //берем из eventData объект, который к нам перетащили, из из него берем компонент Drag if (drag != null) //проверка перетащили ли к нам действительно драг (на всякий случай) { if (transform.childCount > 0) //если у нас (у ячейки) детей больше 0 (т.е. если слот занят) { transform.GetChild(0).SetParent(drag.old); //тогда берем нашего ребенка (занимающего слот) и устанавливаем ему родителя того, //кто находится в переменной old у притащенного к нам объекта //(т.е. смотрим откуда к нам перетащили объект, и туда переносим того, кто тут был раньше) } drag.transform.SetParent(transform); //если в ячейке изначально никого не было, то просто устанавливаем для пришедшего объекта //эту ячейку родителем } } } Quote Link to post Share on other sites
Владимир Шека 4 Author Share Posted June 2, 2018 Версия скрипта с крафтом Цитата Инструкция: Удалите предыдущую версию. Создайте игрока, повесьте на него скрипт InventoryStreamManager. Для подбора вещей необходимо иметь на игроке коллайдер. Скрипт немного бажный: иногда при крафте удаляется вещь, либо создается 2. Но в целом подходит для того, чтобы изучить технологию создания, тем более в видео все подробно объяснено. Полезно для новичков. Но развивать его особо смысла нет, есть "Продвинутый инвентарь персонажа" https://null-code.ru/project/180-prodvinutyy-inventar-personazha.html Скачать InventoryStream.unitypackage или https://yadi.sk/d/yTDKPHpz3WrsGL Quote Link to post Share on other sites
Владимир Шека 4 Author Share Posted July 5, 2018 Тема неактуальна, есть новая версия: Unity: Инвентарь и крафт Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.