Чудесный UI Unity5 или приключения кнопки

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

Затеял я не давно игрулю на юнити и в процессе разработки игры под андроид, наткнулся на одну особенность, оказывается в юнити нет нормальной обработки событий кнопки UI.Button, таких каких Up и Down.

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

На событие OnClick моя функция ClickBtnRight выполнялась лишь один раз, в одном кадре, а если мы удерживаем кнопку то функция уже не запускается. В чем была проблема, пока кнопка нажата мне нужно двигать персонажа вправо, и для этого мне нужно знать когда на кнопку нажали и когда ее отжали. Допустим onClick() позволяет узнать когда нажали на кнопку, но никаких стандартных методов узнать когда ее отжали нету. Поискав немного в Google я узнал что это распространенная проблема и даже нашел ее решение, которое заключалось в том что бы выбрать изменение события на кнопке по цвету, т.е. ColorTint:

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

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

Но я решил проблему иначе, выбрав события на кнопке по спрайту, т.е. SpriteSwap:

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

Я начал каждый кадр отлавливать какой же сейчас спрайт текущей на кнопке, и мне это позволило реализовать

if (btnLeft.GetComponent<Image> ().overrideSprite ==

btnLeft.GetComponent<Button> ().spriteState.pressedSprite) {


//двигаем героя влево


} else if (btnRight.GetComponent<Image> ().overrideSprite ==

btnRight.GetComponent<Button> ().spriteState.pressedSprite) {


//двигаем героя вправо


}


Когда условия срабатывало я просто двигал героя на определенное значение влево или вправо. Так же замечу что конструкция должна быть if else if что бы никогда не сработала обработка одновременно нажатия влево и вправо.

Вот как в целом выглядят у меня кнопки:

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

Так же если вам надо что бы кнопка не выделялась при нажатии просто закидывайте в строчку Pressed Sprite тот же спрайт кнопки просто с другим названием, как собственно сделал я.


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


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


Разрабатываю на Unity 5.3.2 на C# под андроид.


Игра в стадии разработки...хотел показать как двигается персонаж...но пока не могу выкладывать видео)))


Это мой первый пост не судите строго :) Вот вам картинка из игры..

Чудесный UI Unity5 или приключения кнопки Unity, Unity5, Gamedev, Мобильные игры, Android, Платформер, Игры unity, Длиннопост

Лига Разработчиков Видеоигр

6.7K постов22.2K подписчиков

Добавить пост

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"

Автор поста оценил этот комментарий

не за что. по сути кроссплатформинпут тоже работает через events trigger. В след проекте про него не забывай тогда:)

раскрыть ветку (1)
Автор поста оценил этот комментарий

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

1
Автор поста оценил этот комментарий

какой пакет? тебе там 2 скрипта нужно. ButtonHandler и CrossPlatformInput. Если бы вес приложения был важен, то на юнити бы не писал:) он пустой проект метров на 5 собирает, а эти скрипты дай бог если килобайт 5 добавят к весу. Юнити собирает только то, на что есть ссылки в собираемых сценах. У тебя может быть пакетов добавлено на 50 гигов, но apk он соберет на 5 метров.


Вот я использую в проекте, но тут и джой и куча других скриптов еще.

Иллюстрация к комментарию
раскрыть ветку (1)
Автор поста оценил этот комментарий

Пока наверное оставлю триггер событий, все таки он же существует значит это тоже правильное решение)) Да и под кнопки уже все расписано, но учту, это очень полезная штука, спасибо.

показать ответы
2
DELETED
Автор поста оценил этот комментарий

Далее создать элемент канваса Image и закинуть этот скрипт на элемент. Если заморочиться, то можно и свое событие onClick добавить в скрипт. В итоге получаем аналогичную кнопку.


И хочу порекомендовать в дальнейшем не пробовать реализовывать тупые советы из интернета типа определять по цвету или по картинке ибо это настолько не стабильно, что может перестать работать например если за окном дождь пошел. :))

раскрыть ветку (1)
Автор поста оценил этот комментарий

я все сделал как тут советовали в коммента на триггере событий, работает отлично.

Автор поста оценил этот комментарий

Это называется "кеширование" и это есть хорошо.

Но кеширование в костыле не есть хорошо. Используйте стандартный компонент:

#comment_75800517

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

раскрыть ветку (1)
Автор поста оценил этот комментарий

да вроде Event Trigger не самопал

Автор поста оценил этот комментарий

assets->importpackage->crossplatforminput



вот простейший кусок кода, в данном случае для джоя, с кнопкой будет одна строчка


h = CrossPlatformInputManager.GetAxis (axisHorizontal);

v = CrossPlatformInputManager.GetAxis (axisVertical);

transform.position+=new Vector2(h,v);


получаем полноценный хэндл управления

кнопке задаем этот axis (в project settings->input)

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

раскрыть ветку (1)
Автор поста оценил этот комментарий

Это оказывается пакет качать надо, я то думаю почему ничего нет..

А это не усложнит по сравнению с тригерром событий? Я делаю на андроид...тут вес приложения важен тоже, этот ассет много добавляет МБ в игру?

Вообще я не планирую на пк и вебджиэль, но это хорошая тема crossplatforminput

показать ответы
Автор поста оценил этот комментарий

ну во-первых обращение идет не напрямую, а parent.var. Во вторых я хз как работает GetComponent, но уж точно Obj.image будет быстрее, чем Obj.GetComponent<Image>() поскольку происходит своеобразный поиск компонента, принадлежащего классу. В третьих он проверяет взятый компонент на null каждый раз. В этом можно убедиться взяв компонент, которого не существует GetComponent<NetworkManager>() попробуй например.


в общем это выглядит примерно так, 2 варианта

№1:

-Обращаемся к родителю

-Запускаем какую-то непонятную функцию, которая хз как ищет нам переменную, принадлежащую к указаному классу

-проверяем её на null

-в конце концов возвращаем переменную, ей можно пользоваться


№2

-переменной можно пользоваться

раскрыть ветку (1)
Автор поста оценил этот комментарий

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

Автор поста оценил этот комментарий

И если еще хорошенько подумать - использовать CrossPlatformInput и не изобретать велосипед. Да и для движения удобней джой использовать, а не кнопки. Нажал в любом месте экрана например, рисуется стик и начинается управление. И экран не захламляется и более точные движения получаются. Мы когда предыдущую игру писали на андроид - управление было и на джойстике (физический который, от XBOX или PS) и на таче и хз на чем еще, может кому взбредет в голову клаву подрубить к андроид-устройству. Все работало и кода было куда меньше чем здесь. Единственное 2 раза в секунду проверял с какого устройства идет инпут и менял метод ввода (например если на джойстике начал управлять - кнопки с экрана скрывались, чтоб не мешать и т.д.)

раскрыть ветку (1)
Автор поста оценил этот комментарий

Пример в студию)) а то все только говорят

показать ответы
Автор поста оценил этот комментарий

я так понял видео про кросс-платформ инпут. Там как раз проще некуда. Добавляешь компонент на кнопку, там одно свойство типа string. Пишешь в него "Left". В юнити в инпуте задаешь параметр Left. В коде if (Input.GetButtonDown("Left"){}. Все. Одна строчка кода. И самое интересное, что если ты сбилдишь это под винду или webGL или захочешь подрубить икс-боксовский джой, то все это так же будет работать без единой добавленной строчки кода

раскрыть ветку (1)
Автор поста оценил этот комментарий

Вот это уже круто, а как работать то с этим? набросай пример

3
DELETED
Автор поста оценил этот комментарий

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

раскрыть ветку (1)
Автор поста оценил этот комментарий

Ну я только учусь :)

Опиши пример как пользоваться тригерром событий?

1
DELETED
Автор поста оценил этот комментарий

AddComponent -> Event -> Event Trigger, нету?

раскрыть ветку (1)
Автор поста оценил этот комментарий

О есть, правда я этим не пользовался еще, как он работает?

показать ответы
DELETED
Автор поста оценил этот комментарий
1. Как только ты подключаешь uGUI автоматически создается эта система в сцене, т.к. uGUI работает за счет Graphic Raycaster. Он добавляется на Canvas.

2. Это работает и для тача при наличии в сцене компонента Touch Input Module.

3. В каждое событие присылается присылается PointerEventData, который содержит избыток информации по всем параметрам указателЕЙ. Их может быть много, по количеству пальцев. И да в этой структуре есть информация о пальцах (тачах).


https://docs.unity3d.com/ScriptReference/EventSystems.Pointe...

раскрыть ветку (1)
Автор поста оценил этот комментарий

я это все читал, и как это работает не понял, не нашел не одного примера в доках. Ну в целом стоит этим пользоваться если все решается в один if else if?

показать ответы
3
Автор поста оценил этот комментарий

А потом люди искренне удивляются - почему это профессионалы надменно относятся к сишарп кодерам.

раскрыть ветку (1)
Автор поста оценил этот комментарий

Пускай относятся))) что с того)

Автор поста оценил этот комментарий

Вообщем завершающий коммент, я перешел на Event Trigger за место костылей и очень все хорошо работает :) Всем спасибо!

Автор поста оценил этот комментарий

Event Trigger отменили ? Юзай его, что за люди пошли, не знают всего что есть в Unity и сразу посты писать...

раскрыть ветку (1)
Автор поста оценил этот комментарий

Я могу и вас уколоть))) "Что за люди пошли, все комменты не прочли и сразу свой лезут писать"


Я уже писал что переделал все на триггер событий.

1
Автор поста оценил этот комментарий
if (btnLeft.GetComponent<Image> ().overrideSprite ==
btnLeft.GetComponent<Button> ().spriteState.pressedSprite) {

серьезно? я бы такой костыль даже когда в школе учился не поставил:)

раскрыть ветку (1)
Автор поста оценил этот комментарий

я уже переделал на тригер событий как показали ниже

Автор поста оценил этот комментарий

на старте Button button = GetComponent<Button>();

потом вызывай как button, чтоб каждый раз по id её не дергать, тормознуто довольно

раскрыть ветку (1)
Автор поста оценил этот комментарий

А что такого если каждый кадр обращаться к Obj.GetComponent<Image> за место переменной? Как это влияет?

показать ответы
3
Автор поста оценил этот комментарий

А ещё ты каждый кадр юзаешь GetComponent

раскрыть ветку (1)
Автор поста оценил этот комментарий

Это плохо? можно переделать так что бы при старте юзать а дальше переменную

показать ответы
Автор поста оценил этот комментарий

Посмотрите вот это видео https://www.youtube.com/watch?v=nGYObojmkO4

раскрыть ветку (1)
Автор поста оценил этот комментарий

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

показать ответы
Автор поста оценил этот комментарий

Лучше бы на форуме спросил или мануалы почитал)

Сравнивать спрайты конечно гениально))

раскрыть ветку (1)
Автор поста оценил этот комментарий

Так я читал)) писал же пример там люди цвета сравнивали))) По моему просто и эффективно чем сложное что то писать))) Мне ж главное просто отловить нажата ли кнопка в кадре и все)

Автор поста оценил этот комментарий

Для управления персонажем под мобилки в Unity лучше писать свои кнопки.

раскрыть ветку (1)
Автор поста оценил этот комментарий

Ну меня устроил мой подход, главное я каждый кадр знаю нажата кнопка или нет :)

показать ответы
6
DELETED
Автор поста оценил этот комментарий

С применительной точки зрения, нужно использовать компонент Event Trigger.

С программной точки зрения


using UnityEngine.EventSystems;


[DisallowMultipleComponents]

public sealed class SomeClass : MonoBehaviour, IPointerDownHandler, IPointerUpHandler

{

____public void OnPointerDown(PointerEventData eventData)

____{

____}


____public void OnPointerUp(PointerEventData eventData)

____{

____}

}

раскрыть ветку (1)
Автор поста оценил этот комментарий

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

показать ответы
4
Автор поста оценил этот комментарий

посмотри на это:

Иллюстрация к комментарию
раскрыть ветку (1)
Автор поста оценил этот комментарий

Это наверное ассет или старшая версия юнити у меня такого нету, с таким конечно было бы проще))

показать ответы