Jump to content

Unity: скрипт на инвентарь от Stream


Recommended Posts

Inventory Script Unity.jpgДля начала посмотрите видеоуроки от Stream:

  1. https://www.youtube.com/watch?v=Y-OpWcRhgJ0 - полностью
  2. 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); //удаляем из списка инвентаря сам предмет
        }
    }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

 

 

 

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д объекта предмета для отображения в мире
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

 

 

 

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
    }
    
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

 

 

 

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); //если в ячейке изначально никого не было, то просто устанавливаем для пришедшего объекта
            //эту ячейку родителем
        }
    }
}

 

 

 

 

Link to post
Share on other sites
 

Версия скрипта с крафтом

 

Цитата

Инструкция: Удалите предыдущую версию. Создайте игрока, повесьте на него скрипт InventoryStreamManager. Для подбора вещей необходимо иметь на игроке коллайдер.
Скрипт немного бажный: иногда при крафте удаляется вещь, либо создается 2. Но в целом подходит для того, чтобы изучить технологию создания, тем более в видео все подробно объяснено. Полезно для новичков. Но развивать его особо смысла нет, есть "Продвинутый инвентарь персонажа" https://null-code.ru/project/180-prodvinutyy-inventar-personazha.html

 

Скачать InventoryStream.unitypackage или https://yadi.sk/d/yTDKPHpz3WrsGL

Link to post
Share on other sites
 
  • 1 month later...
 

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Powered by Invision Community
Поддержка Invision Community в России

×
  • Create New...