Pull to refresh

Tower Defense своими руками, часть 2: Интерфейс и NGUI

Reading time4 min
Views39K
Доброго времени суток, друзья!

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

Но сам пост не об этом. Сегодня я хотел бы поделиться с вами маленькими подсказками по поводу пользовательского интерфейса. О том, чего стоит избежать уже в самом начале разработки, и что потом делать. К сожалению, мой «скилл» недостаточно высок, чтобы писать о чем-то действительно новом и неизведанном в этой области, так что пост будет больше посвящен новичкам в гейм-деве (и в первую очередь тем, кто пока еще боится NGUI), да и пост будет субъективен на все 146%.

image

Итак, самая важное замечание при разработке интерфейса, когда вы работаете в Unity3D: ни в коем случае не пользуйтесь стандартным интерфейсом! На Asset Store (это такой внутри-Unity магазин, где люди делятся своими наработками и готовыми решениями) есть огромное множество различных вариантов GUI-систем, и самым популярным на данный момент является NGUI. Не стоит недооценивать его (или другие GUI-системы), ведь выбор подобной технологии позволит сэкономить кучу времени.

Давным-давно, когда я косо посматривал на NGUI, я считал, что стандартный GUI не так уж и плох — знай себе, да прописывай области для вывода кнопок, и что они делают… На все это дело было потрачена уйма времени и сил, и как оказалось, зря!

Интерфейс оказался слишком медленным… Очень! По итогам работ оказалось, что даже одно окно интерфейса «просчитывается» целых 25 мс (на ноутбучном i5), что оказалось категорически неприемлемым для конечного пользователя. И вот буквально в тот же день, когда я обратил на это внимание, на Asset Store с большой скидкой стал продаваться NGUI. Вот тогда-то все и изменилось.

image

Сам принцип работы NGUI (или любой подобной системы) состоит в том, что все GUI-элементы являются простыми объектами, имеющими свой материал и без проблем отрисовываются даже мобильниками без ущерба производительности. Но тут-то и возникает одна из главных «проблем» (из-за которой я изначально и отказался от NGUI) — приходится выводить отдельные функции для обработки событий, таких как нажатие на кнопку и ей подобные.

Вообще, это не является проблемой, если у вас есть точное представление о том, что «тут у меня будет кнопка выхода из игры, а здесь откроется окно опций». Проблемы начнутся тогда, когда вы захотите динамически выводить разное число элементов и динамически определять то, что с ними делать. Еще больше проблем обнаруживается, когда ты узнаешь, что при вызове Callback-функции кнопкой в NGUI, NGUI не может передавать аргументы для запуска функции.

Я нашел довольно изящное (а может и кривое, кому как :) ) решение, и сводится оно к следующему (все написанное ниже касается Unity3D с NGUI):
Просто напросто в имя объекта-кнопки записывайте все те аргументы, которые вы хотите использовать для вызова Callback-функций. А при вызове Callback-функции воспользуйтесь вот этой замечательной строкой:
UIButton.current.gameObject.name

для того, чтобы считать имя только-что нажатой кнопки. Просто, не правда ли?

Для того, чтобы записать различные агрументы в имя объекта (то есть по сути, сформировать одну строку из разных аргументов), можно пользоваться чем-то подобным:
int itemID = 2;
int count = 15;

string finalString = itemID.ToString() + ":" + count.ToString();
// 2:15

А для считывания этого дела, воспользоваться функцией string.Split(char[]);
Выглядеть это будет примерно так:
char[] dc = {':'};
string[] decoded = finalString.Split(dc);
itemID = int.Parse(decoded[0]);
count = int.Parse(decoded[1]);

Вообще я очень удивлен, почему так мало разработчиков пользуются возможностью записи различных данных в одну строку, а потом декодировать эту строку. Это же так просто и удобно!

Кстати, для тех, кто еще не успел приобщиться к NGUI, подскажу еще парочку полезных функций. Мне пришлось изрядно покопаться в справке, чтобы найти все это и проверить на работоспособность:

1) Добавление элемента интерфейса, дочерним к уже существующему (по сути, это то же самое, что и обычный Instantiate(), но он не работает адекватно в NGUI):
NGUITools.AddChild(parent, prefab);


2) При работе с сетками элементов, рекомендуется использовать вот такую запись вместо привычного Destroy(object):
NGUITools.Destroy(object);


3) Для добавления новой функции в список Callback-функций у кнопки, используем следующее:
GetComponent<UIButton>().onClick.Add(new EventDelegate());
GetComponent<UIButton>().onClick[GetComponent<UIButton>().onClick.Count - 1].Set( MonoBehaviour, "FunctionName");


4) Если хотите изменить размер виджета:
NGUIMath.ResizeWidget(widget, widget.pivot, x, y, minWidth, minHeight);


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

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

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

А быть может, в следующий раз расскажу про Steamworks, если получу зеленый свет на гринлайте.

image
Tags:
Hubs:
Total votes 38: ↑34 and ↓4+30
Comments17

Articles