Совсем недавно, делая редактор диалогов я задумался над тем, сколько рабочего времени я уделяю написанию редакторов и заметил, что самая частая работа, которую приходится делать в этом случае - это работать со стандартным UnityGUI. Ранее я пробовал дописывать свои методы к тому что есть, но меня всегда пугала "ужасность" самого этого гуи, особенно когда начинаешь расписывать объекты, требующие детальной точности.
Довольно-таки часто используемые команды приходилось создавать весьма и весьма непростыми путями, повторять большую-прибольшую кучу кода.
Так в один прекрасный день я сел и начал писать "обертку" поверх старого гуя, которую назвал cssGUI. Конечно, до ксс мне еще далеко, но команды я изначально брал оттуда, отсюда и название.
Уже в первые дни я понял, что обертка хоть и требует дополнительного ресурса, но и делает код в принципе гораздо более выразительным. Сегодня же я добавил дополнительные штрихи и убедился в том, что данная обертка не просто хороша - ее не хватало мне все это время.
Касательно падения скорости я могу сказать что это очень и очень малые единицы, к тому же - эта наработка чисто для редактора, а не для игры, что делает подобное в меру позволительным. Я рисовал через нее довольно-таки сложные гуи и она работала чудесно, отсюда могу заверить что разницы в скорости вы не почувствуете. :)
Итак, что дает нам cssGUI?
Чуток о стандартном GUI
В стандартном ГУИ для обработки стиля требовалось пересоздать стиль и/или инициализировать новые значения для полей.
Например, создание кастомной кнопки аля вот такой:
GUILayout.Button("MyButton", new GUIStyle("minibutton") { padding = { left = 10 } });
Согласитесь, это еще простой вариант?
А что если мы добавим к нашей кнопке ограничение по ширине? Выйдет уже вот так:
GUILayout.Button("MyButton", new GUIStyle("minibutton") { padding = { left = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
Отлично, это уже достаточно ужасно. Но дело в том, что кнопок у нас должно быть 3, и выровнены они должны быть по горизонтали.
GUILayout.BeginHorizontal();
GUILayout.Button("MyButton1", new GUIStyle("minibutton") { padding = { left = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
GUILayout.Button("MyButton2", new GUIStyle("minibutton") { padding = { left = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
GUILayout.Button("MyButton3", new GUIStyle("minibutton") { padding = { left = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
GUILayout.EndHorizontal();
И иметь дополнительный отступ по вертикали перед и после всего этого. Кнопку по середине - показать нажатой. А у кнопки справа делать отступ справа, а не слева
GUILayout.BeginVertical();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Button("MyButton1", new GUIStyle("minibutton") { padding = { left = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
var centerButtonStyle = new GUIStyle("minibutton");
GUILayout.Button("MyButton2", new GUIStyle(centerButtonStyle) { normal = centerButtonStyle.onNormal }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
GUILayout.Button("MyButton3", new GUIStyle("minibutton") { padding = { right = 10 } }, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.EndVertical();
И да, пример еще очень даже красивый. Но нам и его достаточно, чтобы понимать, как сильно начинает разрастаться GUI, когда добавляются даже небольшие дополнительные условия.
Для наглядности, тот же код написанный через обертку cssGUI:
using (gui.group_horizontal(css.space_vertical(10, 0)))
{
    gui.button("MyButton1", "minibutton", css.padding_left(10), css.width_range(100, 200));
    gui.button("MyButton2", "minibutton", css.style_state(x => x.onNormal), css.width_range(100, 200));
    gui.button("MyButton2", "minibutton", css.padding_right(10), css.width_range(100, 200));
}
Помимо этого, мы можем вынести скрипт со стилями в отдельный файл, подобно css и вытаскивать "набор свойств" оттуда.
Отсюда формируется несколько вещей, почему стоит вообще использовать cssGUI:
  • понятность - код гораздо проще читать
  • универсальность - вместо нескольких разных способов мы используем один, в котором описываем все свойства контрола
  • удобство - данный код писать гораздо проще, чем наверстывать буквы в разных регистрах
Помимо всего увиденного данный класс меняет привычные методы-группы аля BeginHorizontal/EndHorizontal и прочие. Возможно применения в двух вариантах:
  1. через интерефейс IDisposable (пример выше с использованием слова using)
  2. аналогично стандартному варианту, но с общим завершающим методом end(), подходящим под все группы
Код файла стилей пока выглядит вот так:
В моем случае - он поддерживает иерархии, то есть те элементы, которые заключены в using - передают свойства следующему контексту. Такой фичи в стандартном GUI просто нет.
В случае же со свойствами без зависимостей код будет просто линейным перечислением стилей.
В целом "модификаторы" могут вот что:
  • модицифицировать прямоугольник
  • подменить/изменить стиль
  • добавить опции GUILayout
  • написать код перед/после элемента
  • изменить состояние объекта
  • изменить контент (например скрыть часть текста и подменить на троеточие)
  • изменить матрицу на время рисования объекта
В данный момент я еще не могу предоставить данную наработку сообществу - класс gui, содержащий контролы активно дополняется новыми в том числе нестандартными контролами. Кроме этого как показывает практика во время работы появляются новые идеи возможных модификаторов. Когда наработка полностью сможет заменить стандартный GUI она будет опубликована. Впредь все свои наработки я пишу на данной гуишке, что обяжет некоторых из вас тоже перейти на него ;)
Очень хотелось рассказать о том что готовится, прям не удержался. Заранее простите.

Сабж вне темы - про Unity-раздел в целом
Сегодня я добавил в проект Unity 2 новых типа возможных ресурсов:
  • анонсы
В них мы можете как я сейчас поделиться тем, что вы намереваетесь предоставить сообществу (как это я сейчас и сделал).
Так же в анонсах вы можете презентовать свою идею с целью позвать людей себе в команду, минуя тем самым создание отдельного проекта.
  • WIP
всем известный способ показывать работу в процессе. В отличии от анонса эти ресурсы находятся в постоянном процессе, тобиш вы можете дополнить их какими-нибудь обновлениями. Постараюсь подтверждать изменения в ресурсах как можно чаще. Сейчас такая деятельность бывает разворачивается в блогах, но возможно стоит найти ей более тематичное место.
Если у нас еще есть игроделы на Unity - не брезгуйте, пользуйтесь :)
0
27
10 лет назад
Отредактирован Devion
0
*Одним ловким комментарием он прыгает в ленту и совсем чуть-чуть поднимает счетчик просмотров*
0
24
10 лет назад
0
Если у нас еще есть игроделы на Unity
то есть они уже перевелись? О_о
0
27
10 лет назад
0
Melissa, ну у нас их изначально немного. Было б побольше, мы б уже натворили тут бардак )
0
9
10 лет назад
0
"всем известный способ показывать работу в процессе. В отличии от анонса эти ресурсы находятся в постоянном процессе, тобиш вы можете дополнить их какими-нибудь обновлениями"
т.е. создать один WIP-ресурс и обновлять его?
1
27
10 лет назад
Отредактирован Devion
1
GeneralElConsul, обновлять, дописывать в комменты, показывать хоть в странице (но ждать пока я подтвержу), хоть в комментах (но сразу) результат. От меня это просто попытка создать общее место для випов и стандартизировать это место. Если випов будет много, то можно будет посмотреть их все по единому адресу /unity/tags/wip, что было бы удобно. Лично я бы с радостью почитал, что другие юзеры делают на юньке, может местами бы посоветовал, местами бы сам поучился. Потому очень бы советовал завести вип и познакомить людей с вашей деятельностью, если она кажется вам интересной.
На мой взгляд наша работа была бы виднее в одном проекте, чем будучи разбитой на десятки мелких постов по блогам и одностраничным проектам. Ну и обратная связь на мой взгляд так будет повыше, ибо внимание рассеивается так или иначе на все випы, если юзер заметит эту фишку в нашем проекте.
0
29
10 лет назад
0
Extravert, кст уже не первый раз встречаю такой классный способ использования IDisposible :D Раньше я думал, что его надо использовать только для тяжелых объектов или объектов использующих дискрипторы, чтобы сразу все подчищать)
0
27
10 лет назад
0
alexprey, ну тут фактически та же цель - вызвать закрытие группы по завершению контекста. Однако удобно это не всегда. Например бывает что внутри контекста формируется переменная, нужная потом вне контекста. В таких случаях конечно лучше использовать раздельные теги открытия/закрытия группы, собственно из этих соображений их тоже оставил. Или например когда открытие/закрытие используется в разных местах, а не внутри одной функции, тоже вариант.
А вообще уже давно взял это за привычку, удобно, стильно, молодежно.

Еще я вот думаю как упростить отдельный скрипт со стилями.
Была мысль использовать CSS разметку, запаковать ее в отдельный файл и по нажатию какой-либо кнопки перезагружать кеш с объектами, на которые она парсится. При том в этом случае есть очень удобная штука - можно редактировать стили без компиляций, прямо в окне unity (благо разметка несложная и парсер правильности там не шибко важен).
Вот, и хотел я значит найти в инете какой-нибудь готовый парсер CSS выражений, сорцы которого можно было бы переделать под себя (чтобы не лепить велосипед с нуля). Однако не нашел пока ничего годного/выразительного под шарп.
0
29
10 лет назад
Отредактирован alexprey
0
0
27
10 лет назад
0
alexprey, это первое что я скачал ) какой то он гигантский в реализации, потому отказался.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.