Универсальная система способностей(спеллов) часть XII

Научился сам? Помоги начинающему.

Универсальная система способностей(спеллов) часть XII

Сообщение lawsonilka 13 янв 2015, 19:02

Создание системы универсальных способностей(спеллов) на unity3D Часть XII

Save и Load системы. Скриптовый объект.

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

Но сначала по теме о хранении способностей.
Когда я только начинал проектировать систему способностей я понимал что мне придется в чемто хранить созданные способности.
До этого я участвовал в одном проекте где нужно было расширить редактор для создания персонажей. Эти персонажи обычно имели
елементарнейшие свойства и более сложные вроде анимаций(пришлось написать свою систему анимаций), поэтому когда уже пришло время
решать как хранить созданного персонажа, я без особых вопросов решил что бинарник binary сойдет для этих целей. Поэтому для каждого
созданного персонажа я создавал отдельно папочку где хранил все его ассеты, а также бинарник с его данными.

С системой способностей так обойтись было не возможно, как я уже понял в процессе ее создания, объяню почему.
Опытные программисты знают что все объекты в unity3d, и объекты в пространстве UnityEngine, все они наследуются от одного базового
объекта который также и называется Object(по аналогии с System.Object). Такая система удобна когда работаешь только в одной области
допустим в области unity3D - с объектами редактора, не выходя за его рамки. Но у этой системы есть и обратная сторона.
Редактор unity3d работает с объектами на уровне визуализации. Что это значит!?
Когда мы создаем новый экземпляр класса или любого другого объекта, этот объект существует только в компьютере на программном уровне,
тоесть этот объект нельзя потрогать или понюхать. Редактор же unity предоставляет пользователю на физическом уровне возможность
воздействовать с объектом, его можно удалить из редактора, копировать, изменять свойства через пользовательский интерфейс. Помните
когда мы создавали редактор способностей, мы рисовали свойства каждого компонента в нем самом - что получается он сам представляет
свою реализацию. Также и в unity, каждый, буквально каждый объект наследующийся от Object, начиная от элементарного TextAsset до GameObject, имеет свой стандартный редактор, вы его(редактор) видите в окошке Inspector каждый раз когда создаете объект.
Редактор unity3D для хранения всех этих объектов имеет свою, специфичную, систему сериализации.

Как я постоянно говорю, эта система способностей, состоит из компонентов, которые в свою очередь могут нести любую информацию, будь
то число или строка или текстура, или даже объект.
И если с числом и строкой все понятно, можно было бы их хранить в том же бинарнике то с объектами, unity объектами, все немного
сложней. Просто так вы их не сериализуете в какойто файл.
Скрытый текст:
Есть удачные решения позволяющие это сделать, но они также как и сериализация в unity3D - специфичны.

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

Поначалу я думал использовать ссылки на объекты, обычные строковые ссылки для unity объектов, а для елементарных типов данных
отдельно создавать TXT файл куда бы записывал два значения: это "цель" компонента и его значение ввиде строки. Это бы выглядело так,
есть способность, далее в редакторе она состоит из двух файлов, первый показывал бы на какие объекты(unity объекты) ссылается тот или иной
компонент. Второй файл в виде TXT, показывал бы какие елементарные типы данных содержит каждый компонент способности. Т к
елементарные типы можно парсировать(TryParse метод) в их значения из строк, то с этим сложностей не должно было возникнуть - с чтением файла.
Сложность возникает с компонентами с КОНКРЕТНОЙ реализацией такими как AbilityTimeComponent, я ведь не могу записать в файл всю его
конкретную реализацию. Поэтому идею с двумя файлами пришлось откинуть.

Потом меня посетила идея использовать zip архивы. Сохранять все отдельно сериализованные объекты в архив, а компоненты имеющие
объектные значения, просто бы копировали эти объекты в архив и сохраняли ссылку на них. Этот вариант поначалу меня устраивал тем что
вся система сразу представляла собой один архив который был запечатан от постороннего вмешательства. Опасения вызывали у меня только
размеры каждого такого файла, также необходимо было написать среду в которой создавался бы архив и его распечатку при запуске игры.
Скрытый текст:
Есть плагины для программного архивирования, у того же WinRaR

Поэтому от этой идеи тоже пришлось отказаться.
Тогда я перешел к идеи с бандлами(AssetBundle), это что то вроде тех же архивов только более понятные для unity. Но они работают только в платной версии unity3D, поэтому вся универсальность системы теряется для тех у кого нет платное версии. И от этой идеи пришлось отказаться.

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

Скриптовый объект.

Скриптовый объект в первую очередь такой же объект как и все остальные в unity3D, тоесть он наследуется от UnityEngine.Object, и
поэтому как и все остальные объекты имеет свой собственный редактор.

Почему именно скриптовый объект!? Как я говорил выше все объекты создаваемые программистами существую только в виртуальном виде,
редактор же unity позволяет представить объект в физическом виде. Этот физический объект лежит в какой то папке и его можно удалить
или изменить и тд. Скриптовый объект можно рассматривать как обычный unity компонент.
Вот вы написали компонент который наследуется от MonoBihaviour и добавляете(создаете) этот компонент на объекте, вы сразу же в окошке
Inspector видите свойства компонента - можно сказать что он из виртуального вида перешел в физический, теперь вы можете удалить этот
компонент или изменить его свойства в инспекторе.
pic28.png

Как видно на изображении, в редакторе скриптов объект приобретает виртуальный вид, но как только вы добавите его объекту он принимает
физический вид. Поэтому мне и нужно чтобы мои созданные способности которые я создаю с помощью оператора new() представлять в виде
физических объектов в редакторе. Это дает много преимуществ против бинарной или XML или любой другой сериализации. Редактору unity
намного легче работать с объектами из его области, отсюда и пользователю будет удобнее работать с объектами которые имеют хоть какую то
физическую форму.

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

О недостатках могу сказать немного. Единственная самая неудобная для меня вещь была, так это сам редактор скриптового объекта.
Как я выше сказал, любой объект в unity3d имеет СВОЙ редактор, тоесть каждый объект имеет свою реализацию.
Скрытый текст:
На самом деле базовый редактор каждого объекта автоматизирован, он с помощью рефлексии определяет какие свойства будут
отображаться в нем, и только расширяя его, пользователь может изменять способы отображения информации.

А т к у нас есть аж четыре вида объектов, четыре вида способностей: пассивная пустышка, активная пустышка, пассивная, активная,
поэтому и придется создавать четыре отдельных редактора. Может это и звучит сложно, хотя там работы будет минут на 10-15, и еще не
самая сложная задача.

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

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

Следующая часть

автор: этот хрен, он же llka, он же lawsonilka
У вас нет доступа для просмотра вложений в этом сообщении.
lawsonilka
UNIверсал
 
Сообщения: 390
Зарегистрирован: 21 окт 2014, 14:48

Вернуться в Уроки

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 4