Войти
UnityФорумПрограммирование

Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

#0
(Правка: 16:34) 14:13, 23 фев. 2021

Вероятно что-то опять элементарное, но не понимаю такой штуки... может подскажете, как бы поудобнее с этим работать.

Опять же есть Unity и C#

Разбираюсь с созданием инвентаря.

- Есть массив ячеек типа Image, это клетки инвентаря расставленные как нужно, добавлен там скроллинг, спрайты маски ну все в общем что нужно.

- Есть массив ScritableObject, в котором записано какое-то количество предметов... спрайт, название ну и тд

При запуске игры, или там при нажатии кнопки или еще чего, проходим массив ScriptableObject и расставляем иконки дочерними объектами в массиве типа Image выставляем размер, то есть отображаем предметы из типа имеющихся у персонажа на экране в нужном месте бекпека.

А далее вот начинается проблема и непонятка для меня:

После расстановки иконок из Массива ScriptableObject в массиве Image (в слотах)
теряется связь между массивами (для меня не могу это осмыслить).

-  Делаем перемещение этих иконок в бекпеке и на клетки для одевания персонажа... все бы хорошо, все двигается меняется классно, но тупняк в том, что как индексы то связать адекватно, что бы в массиве ScriptableObject поменять элементы местами, или же поменять какой-то параметр в элементе этого массива, что бы понимать где что находится? Или считать данные о предмете?
Нужен индекс элемента, а есть куча квадратиков. (Да я их все знаю и могу найти начальную точку...)

В общем целом я могу проверять после окончания перетаскивания предмета все слоты на наличие потомков,

InventorySlots[0].transform.childCount > 0

и понимать, что изменилось, исходя из того, что было на начальном этапе. Привести все в соответствие, можно, но основываясь на названии и изменении другого массива как-то бредово.
Двигаем предмет: Sword (UnityEngine.GameObject) Предмет находится над: Inventory_Slot Родитель слота: Slots_List Текущий Родитель: Game_Screen_UI LastParent = Inventory_Slot
Закончили перетаскивание.
Клетка 0 стала пуста, в клетке 4 появился дочерний объект Name=Sword

и судить есть там что-то или нет, так же могу проверить название и типа по нему как-то судить что за предмет, нооооо:

А если предметы называются одинаково, но с разными характеристиками? Уже будет неверно.

Так вот не понимаю... есть массив клеток расположенный на экране, а как получить индекс этой самой клетки когда с ней взаимодействуем? Есть только картинки как вижу...

Есть такая команда:

GetSiblingIndex()

Но как вижу она определяет индекс элемента в иерархии, и если я туда добавлю элемент который не будет относиться к массиву, собьются индексы.


#1
(Правка: 18:29) 18:28, 23 фев. 2021

FourGen
Вы занимаетесь совершенно ненужными вещами.
Вам не нужны никакие индексы, никакая связь между массивами. Ничего этого не нужно и так не делается.

Создайте скрипт (monobehaviour), назовите его ItemInstance.
В нем сделайте поле содержащее либо ссылку на ScriptableObject для предмета, либо Id предмета(не индекс, а уникальный ID!), либо держите там сами характеристики предмета.
Этот скрипт ItemInstance повесьте на вашу ячейку.
При перетаскивании, будет перетаскиваться и ItemInstance. И вы всегда будете иметь доступ к вашему предмету, куда бы вы его не перетаскивали.

#2
(Правка: 19:15) 19:09, 23 фев. 2021
При перетаскивании, будет перетаскиваться и ItemInstance. И вы всегда будете иметь доступ к вашему предмету, куда бы вы его не перетаскивали.

Ну в том-то и вопрос, что так без проблем все работает, но я как-то все же склонен контролировать, где что находится и как перемещается. Если есть массив, то он должен меняться в тот вид как расположено все остальное, например те же ячейки инвентаря, то есть они должны быть полностью идентичны, а не то, что в инвентаре предмет лежит в ячейке номер 12, количество ячеек динамическое, в массиве он 5й, а размер массива вовсе 7...

Просто я пока не уверен на 100%, что удастся, но я планирую полностью отойти от этих навешанных скриптов, которые что то выполняют, ибо они нафиг не нужны. Да удобно, но такое количество ссылок друг на друга, это какой-то изврат. Мне все же нравится контролировать полностью, что у меня храниться и как выполняется. При текущем подходе сложно будет создать скрипты, которые можно использовать многократно без доработок и запоминания что куда ссылается, кучи переменных навешанных и тд.
Навешивать можно что-то типа того, о чем мне в прошлый раз ответили... эвенты/делегаты
Все события экранные обрабатываются и их можно получить, и смысла навешивать скрипты куда-то нет, так как я и так знаю, где у меня что расположено.
Для примера тот же инвентарь... я знаю куда я нажал, знаю номер ячейки, знаю что в ней под ней и на чем она. Скрипта который отправляет событие достаточно... а не здоровенный скрипт на каждую из миллиона ячеек который делает одно и то же.

Но вроде сделал через GetSiblingIndex(), криво конечно вынес в отдельные элементы интерфейса все эти ячейки.

Взяли из инвентаря из элемента массива №: 2
Надели на персонажа в элемент массива №: 5
Закончили перемещение предмета
Сняли c персонажа из элемента массива №: 2
Положили в инвентарь в элемент массива №: 8
Закончили перемещение предмета

Как-то так получилось..., но вопрос все равно не решен.

#3
19:18, 23 фев. 2021

Ничего не понятно, но очень интересно.
Как можно выставить дочерними объектами иконки в массиве?  Хех, вам надо прогуляться)

"После расстановки иконок из Массива ScriptableObject в массиве Image (в слотах)
теряется связь между массивами (для меня не могу это осмыслить)."
Я с чего она должна появиться то? Что вообще за такая связь между массивами? Ссылки на него? Что-то типа "int array_1 = array_2;"? Ничего не понимаю. Если вы берете значение из одной ячейки массива и приравниваете это значение другой ячейке, то ни какой связи быть не может. Если вы создаете ссылку на массив, то оперировать ссылкой как объектом не можете.

В целом да, Zeus44 дело пишет. Я точно так же создаю ячейку, пусть будет инвентаря, как отдельный самостоятельный объект который содержит в себе всю необходимую информацию, начиная от того кто ее создал и заканчивая что она должна сделать при событии. Когда она нужна, я создаю ее на сцене, заполняю всю необходимую информацию, а потом просто удаляю.

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

Не надо бояться оперировать в юнике игровыми объектами, поскольку в ней это просто ссылки. Их может быть сотни тысяч. Бояться надо покадровых вычислений)

#4
(Правка: 20:15) 19:40, 23 фев. 2021

>sledo

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

Сорри, я часто криво формулирую мысли.
Вот Вот я именно про то, что вы написали... я просто пытаюсь понять есть ли какая-то прямая связь между этими вот вещами:

public Image[] InventorySlots;
на это я в инспекторе перетащил свои ячейки

ячейки отрисованы на экране

public Item[] InventoryItems = new Item[27];
массив этих самых скриптаблобжекс

в цикле изображение из Item назначаем потомком Image, то есть расставляем предметы...

Все расставилось все работает, предметы в инвентаре показаны НО сами то картинки на экране, в которые я присвоил массив своих ячеек, как связаны с этим массивом?

Блин мне даже не сформулировать, я не знаю терминологии.

public Image[] InventorySlots;
на это я в инспекторе перетащил свои ячейки

Но как это назначение связано-то? Массив отдельно картинки отдельно? Нафига тогда оно требует в инспекторе указать ссылку на эти объекты а не программно их назначить эти ссылки?

Вот кажется понял, что хочу спросить!

Я на экран положил картинку, в коде сделал переменную для эту картинки, в инспекторе положил в эту переменную картинку с экрана...

Каким взаимодействием с картинкой на экране в игре, я могу получить связь с переменной в коде?
Или но просто в инспекторе назначается, что бы не дай Бог не было пустых значений и что-то не упало?

Вот еще раз:
Создали вот такой массив:
Pic05 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

Далее у меня есть пачка картинок этих самых слотов
Pic03 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

Так как я создал публичную переменную оно просит перетащить в нее что-то, я перетащил свои слоты выше
Pic04 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

Далее при старте, я в цикле создаю иконки от предметов и присваиваю их на слоты по очереди
Pic06 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

В итоге получаем все как надо:
Pic02 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

Но как связаны эти иконки на экране, с массивом который я создал?
Я ими заполнил массив иконок, но они не имеют ни индекса, ничего... но массив на месте и я могу обратиться к любой из них, но изменяя что-то на сцене, я не получаю изменения массива?

#5
20:07, 23 фев. 2021

FourGen
Кажется я понял в чем дело. Очевидно вы перетащили в поле инспектора префабы из поля Project, а оперируете объектами которые на сцене. Нет, еще раз - все что на сцене это ссылки на объекты которые у вас находятся в Project. Так что либо вы оперируете только ссылками, т.е. с объектами на сцене, т.е. перетаскиваете в свойства все что на сцене, либо вы создаете новую ссылку на префаб (объекты сохраненные в Project со сцены, которые в свою очередь так же являются набором ссылок) и уже опять же оперируете на сцене с объектами только которые находятся на сцене.

В целом это можно представить примерно так - куб на сцене ссылается на префаб, префаб ссылается модель.fbx. Изменяя куб, вы не меняете свойства префаба, а изменяя префаб, не меняете свойства модели. Изменяя свойства модели вы меняете и префаб и куб на сцене. Изменяя префаб, бы меняете свойства куба. Можно удалить связь куба на сцене и префаба в Project, точнее ссылку куба на этот префаб, тогда куб будет иметь ссылки на саму модель.
В этом и прелесть Юнити - вы ограничены только пониманием того что у вас вообще творится на сцене, а самих объектов на сцене, может быть бесчисленное множество, потому что это не объекты, а ссылки на него.

#6
20:38, 23 фев. 2021

Дополнение, написал до того как были добавлены картинки.

В общем да, массив отдельно картинки отдельно.

FourGen
> Но как это назначение связано-то? Массив отдельно картинки отдельно? Нафига
> тогда оно требует в инспекторе указать ссылку на эти объекты а не программно их
> назначить эти ссылки?
Он ничего не будет требовать до тех пор, пока вы не обратитесь к этой ячейке, в которой должна содержаться ссылка на объект, т.к. в противном случае ячейка возвращает null. Собственно это со всеми переменными, просто в том же int по умолчанию будет 0, так что не нужно явно указвать ее значение. А так да, раньше надо было обязательно указывать значения и для int, собственно для локальных переменных надо до сих пор явно указывать их значение в C#.

Легко предупредить такое развитие событий

if(charInventory.Item[a])
{
//что-то делаем
}
else
{
charInventory.Item.RemoveAt(a);
}

Связь я указал выше - это просто сслыки на объекты в Project. Что вы делаете с этими ссылками, вам надо контролировать самостоятельно.

#7
(Правка: 22:10) 21:59, 23 фев. 2021

То есть образно говоря, получается, что все что на сцене, это так сказать значения переменных в том или ином виде? Перетаскивая их в инспекторе на переменную, которую я создал в коде и которая стала доступна в инспекторе, я просто присваиваю значение переменной в коде?

То есть я выполняю что-то типа: переменная в коде = значание переменной (объект на сцене), а не переменная в интерфейсе = переменная в коде. То есть я перетащил не массив картинок, а значения, так сказать?

Я просто почему-то был уверен, что если один и то же тип у данных, то на сцене то же переменные и не понял почему к ним нет доступа из кода как к переменным, а только как объектам...

Я просто не имел дела с таким подходом, если что-то нужно обычно сам это создаешь и работаешь с этим объектом, а тут получается, что объект создается в одном месте, а из кода можно к нему обратиться.

Странно в общем, но вроде понял, спасибо, я все же думал какая-то обратная связь должна быть, если одно другому присвоено и это создано в разных местах.

P.S.

if(charInventory.Item[a])
{
//что-то делаем
}
else
{
charInventory.Item.RemoveAt(a);
}

Из кода не проблема, это я вроде все знаю... ну что-то по крайней мере...
Я просто думал, что из картинки можно как-то получить имя переменной, где оно храниться, если эта картинка создана отдельно от переменной и присвоена ей в инспекторе.

#8
1:10, 24 фев. 2021

FourGen
> Странно в общем, но вроде понял, спасибо, я все же думал какая-то обратная
> связь должна быть, если одно другому присвоено и это создано в разных местах.
Нет, не должно быть. Еще раз - это ссылки на объекты, они работают только в одну сторону - в сторону объекта. Из объекта получить ссылку нельзя. Из ссылки получить объект можно. Получить переменную которой присвоено значение ссылки - мне даже представить такое сложно. Любой поиск по массиву идет путем перебора этого массива, просто в последних версиях языка это происходит не явно. Поэтому это не рекомендуется, ибо медленно. Причем для массивов вроде как поиск так и не сделали, есть только для списков.

FourGen
> То есть я перетащил не массив картинок, а значения, так сказать?
Именно так. Только даже не значения, а опять же ссылки на эти значения. Вкратце, пример "int[] array_1 = array_2;" - полностью описывает это. Создается ссылка на массив array_2, а не экземпляр массива. Я могу присвоить новые значения arrаy_1, но поскольку это лишь ссылка при новой итерации array_1 сошлется на array_2 и вернет его значения. А array_2 не знает что на него есть ссылка, потому как ему вообще плевать. В свою очередь "int[] array_1;" создаст новый экземпляр объекта который вообще не будет знать о array_2 пока в него не поместят на него ссылку. Точнее он и продолжит не знать о нем, а просто будет иметь в переменной ссылку на array_2. А вот чтобы получить к нему доступ, через ссылку в array_1 уже надо будет писать отдельную логику.

UnityФорумПрограммирование