Войти
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 уже надо будет писать отдельную логику.

#9
1:21, 2 мар. 2021

FourGen
все еще не прочитано , что писано , но на вскидку есть пара вариантов
один просто как показательность - это ячейки баффить чем-то булевым или иным
есть/нету и т.д. тут надо думать

и другой вариант , так как похоже что ты пытаешься разрабатывать
технологию называемую ака Drag & Drop | drag and drop
то может есть смысл поискать / по-гугглить или вообще запросить
в самом "юнити поиске" или даже порыться в юнити ассетах
.. может что найдется :) я тоже хочу развитый инвентарь и все хотят :))

#10
(Правка: 10:39) 10:32, 2 мар. 2021

Да он просто делается, вон sledo пытается вам помочь.
Иконок всегда 20, они либо пустые, либо с предметами. Их не может быть больше или меньше. Их всегда строго определенное количество.
Нет слова переместили оружие из 3 слота в 5ый. Есть только событие, что 3ий и 5ый слот поменять местами, было ли там пусто, пусто ли в 5ом вообще не имеет значения.
Var tempSlot = slot5;
slot5 = slot3;
slot3 = tempSlot;
Хранить в слотах лучше структуры.
Ввести несколько методов
MoveSlot(int source, int destination);
IncreaseSlot(int slotIndex, int amount);
Decrease Slot(int slotIndex, int amount) ;
int GetFreeSlotIndex();

#11
(Правка: 15:35) 15:07, 2 мар. 2021

Спасибо, за помощь, Sledo уже все объяснил. Я просто все же надеялся, точнее был уверен, что через графику можно получить название переменной. Не знаю почему, но был уверен.

А так я уже сделал.

Wolfraider

пытаешься разрабатывать
технологию называемую ака Drag & Drop | drag and drop

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

Ввести несколько методов

Зачем методов кучу делать? Скрипт должен выполнять конкретную функцию и все должно быть в нем. Максимум получение каких-то глобальных параметров или их перезапись.
Хранить в слотах лучше структуры.

Я в слоте храню Sprite и индекс элемента в массиве, в общем целом да структура.
Есть только событие, что 3ий и 5ый слот поменять местами, было ли там пусто, пусто ли в 5ом вообще не имеет значения.

Такой подход приводит к багам.
Если слоты не являются переменными (как уже выяснили выше), по ним ничего определять нельзя!
Есть массив, все должно проверять в нем, а то что там нарисовано в этих клеточках пофиг. В случае бага по графике (не знаю, например), массив всегда будет верным и при следующем открытии инвентаря картинки расставятся правильно в любом случае.
Скриншот 02-03-2021 15.17.11 | Связь между массивом картинок и массивом объектов, не понимаю как адекватно получать индексы

Вот для примера... Если не проверять то куда кладешь, положить можно как на панель для слотов... так же в связи с тем, что иконка предмета прозрачная... вокруг предмета луч попадает на сам слот, из-за этого можно положить 2 предмета и более в 1 слот и если это не проверять, то затрется предмет ну и там еще 2 десятка чего можно сделать. Так что по любому надо понимать куда двигается картинка, и если бы сразу бы понимать, что это за переменная, то проще было бы проверять.

Менять значения, основываясь на интерфейсе, для меня выглядит бредово...

P.S. Хотя может я и не о том.... Да есть событие и его отрабатываем. Именно так и есть.

P.P.S

Var tempSlot = slot5;
slot5 = slot3;
slot3 = tempSlot;

Я понимаю, но я всегда должен проверить что мы перетаскиваем...
if (slot5 == null) ...
if (slot3 == null) ...
Если не делать таких проверок, то потом вылезет такое количество глюков... что пипец. Фиг найдешь, где оно не так меняет. Так же еще сюда по хорошему надо вставить исключение...
try
ля ля ля
Что бы так же найти проблему в дальнейшем...

#12
(Правка: 19:39) 19:36, 2 мар. 2021

FourGen
> Если не делать таких проверок, то потом вылезет такое количество глюков
поэтому я и говорю про стуртуры, структуры не бывают null

public struct Item 
{
..
}
https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference… -types/struct

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

#13
21:52, 2 мар. 2021
в любом случае, даже null, это не проблема и проверки не нужны

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

Спрайты надо переносить для визуализации перемещения предмета. Ставить его на новое место или менять текстуру на этом месте и удалять тот что тащили или скрывать это уже не суть важно.

Я знаю, что такое структуры, но я пока не изучал вопрос как с ними работать в C#, надо понять есть ли тут типизированные файлы, (скорее наверное да чем нет),надо посмотреть как с ними работать и тд... Я не знаю как оно память очищает после всего этого... я пока массивами даже боюсь пользоваться... Вроде утечек нет, как это ни странно, вроде все само по себе очищается. но меня это сильно напрягает... Бросать по середине функции массив заполненный и временные указатели... на объекты это жесть, но вроде ничего не падает, вроде все затирается.
Когда я выбирал как хранить, пока остановился на SriptableObject, вроде пока работает и структуры не понадобились (пока) как оно записано, как это прочитать и прочее я не заморачивался... само что-то делает ну и пусть делает..., вроде пока не глючит. Как понадобится поменяю.

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

В общем смысла нет пока нет необходимости.

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