Как стать автором
Обновить

Система SMS поп-апов в приложении на Unity: админ-панель и как удобно работать с информацией

Время на прочтение6 мин
Количество просмотров1.3K

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

Заметка от партнера IT-центра МАИ и организатора магистерской программы “VR/AR & AI” — компании PHYGITALISM.

Система поп-ап окон в приложении 

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

Рис 1. Пример презентации с данными для анализа в нашем решении
Рис 1. Пример презентации с данными для анализа в нашем решении

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

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

Рис 2. Пример кнопки SMS, которая при нажатии отобразит поп-ап с информацией.
Рис 2. Пример кнопки SMS, которая при нажатии отобразит поп-ап с информацией.

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

С какими проблемами мы столкнулись? 

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

В первой версии как только пришел запрос на добавление информации, мы просто вручную помещали данную SMS в нужный Игровой объект (Game Object), а затем присваивали ей ID. Для одной-двух SMS это было приемлемо и не занимало много времени и усилий разработчиков, но перед каждым релизом и показом приложения перед заказчиками, аналитики (администраторы) все чаще просили “быстренько” поменять контент или позицию, или вообще добавить новую SMS. Запросов на добавление таких SMS становилось все больше, у нас возникали трудности с поддержкой данной системы, т.к. параллельно разрабатывался функционал, который менял дизайн элементов, и нужно было постоянно менять и вносить правки. В один прекрасный момент, эти проблемы дошли до критической массы и было решено написать нормальную систему, максимально рассчитанную на кастомизацию администраторами.

Рис 3. Проблемы, с которыми мы столкнулись при разработке Unity-приложения и добавлении в него новой информации
Рис 3. Проблемы, с которыми мы столкнулись при разработке Unity-приложения и добавлении в него новой информации

Решение проблем: админ-панель и система якорей и контейнеров

Как решение мы придумали систему якорей и контейнеров. Это система, которая говорила администратору, что в данное место можно привязать SMS кнопку. В рантайме приложение можно перевести в режим администрирования, в котором администратор может видеть точки “монтирования” SMS.

Рис 4. Красными квадратами отображается возможное место монтирования SMS
Рис 4. Красными квадратами отображается возможное место монтирования SMS

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

Разработанная система состоит из нескольких элементов: админ панели, SMS поп-апа и SMS-кнопки. 

Рис 5. Элементы разработанной системы
Рис 5. Элементы разработанной системы

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

Давайте кратко рассмотрим каждый элемент данной системы по отдельности.

Admin panel

Админ панель – это простое меню, где можно задать контент для поп-апа непосредственно в рантайме приложения.

Рис 6. Админ панель в приложении
Рис 6. Админ панель в приложении

Админ панель состоит из совокупности нескольких блоков, где блок - это определенный тип информации которое нужно отобразить в раскрывающемся попапе. Блоки обговариваются между разработчиками и командой аналитиков. На данный момент их в приложении 3 вида: ссылка на изображение, изображение с компьютера (загрузка на сервер в последствии) и текстовый блок – аналог HTML страницы.

Реализация меню достаточно простая: каждый блок является динамически добавляемым и легко подменяется через простой механизм “Tabbed Menu”. Нам необходимо лишь для каждого блока наследоваться от указанного Пространства имен.

Рис 7. Пример указания Пространства имен которое используется для построения Админ панели 
Рис 7. Пример указания Пространства имен которое используется для построения Админ панели 

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

Кроме данных о блоках, админ панель содержит информацию о самой SMS, а именно – активна ли SMS в данный момент и какой на данный момент блок выбран. При этом SMS может хранить в себе информацию о всех блоках сразу для удобства работы с информацией.

Рис 8. Пример Меты для конкретного блока.
Рис 8. Пример Меты для конкретного блока.

SMS (pop-up)

SMS, или поп-ап – всего лишь подставляемый презентер во время нажатия на кнопку на сцене. Подставление происходит динамически, в зависимости от того, что хранится в самой мете.

Рис 9. Код Меты которая отправляется на сервер.
Рис 9. Код Меты которая отправляется на сервер.

Визуальное представление (или презентер) для каждого блока происходит в зависимости от типа в мете. Презентер в свою очередь может быть любым, хоть это просто in-put строка или какой-то сложный визуальный элемент по типу HTML Editor.

Рис 10. SMS-поп-ап с информацией в приложении 
Рис 10. SMS-поп-ап с информацией в приложении 

Данное решение позволяет нам не зависеть от какой-то реализации, быстро подменять решения или просто напросто удалять без последствий и рефакторинга.

Рис 11. SMS-кнопка с информацией в приложении 
Рис 11. SMS-кнопка с информацией в приложении 

Заглядываем внутрь: как это работает?

Данный функционал состоит из двух основных классов, которые выполняют всю работу в этой системе: контейнеры и якори. Первый класс – контейнеры, является контейнером как для себя, для других контейнеров и для самого якоря.

public class SMSAnchorContainer : MonoBehaviour
{
   public string id;
   public string fullID;

   protected virtual void OnEnable()
   {
       // если в иерархии выше нет никого, берем свой ИД как основу
       if (transform.parent == null)
       {
           fullID = id;
           return;
       }
       
       // ищем по иерархии все контейнеры и объединяем ИД
       var parentsContainer = transform.parent.GetComponentInParent<SMSAnchorContainer>();
       fullID = parentsContainer != null ? parentsContainer.fullID + "_" + id : id;
   }
}

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

Следующий не менее важный класс – это сам по себе якорь, куда администратор может добавлять SMS. Для якоря, также как и для контейнера, нам необходим ID. Это нужно для хранения информации на сервере и сопоставления с SMS. Работает он достаточно просто: достаем первый попавшийся в иерархии контейнер, берем его ID объединяем с ID якоря.

private void OnValidate()
   {
       if (string.IsNullOrEmpty(id))
           id = Guid.NewGuid().ToString();

       container = transform;
   }

Пример генерация ИД для якоря.

public string FullID
   {
       get
       {
           var foundedAnchorContainer = container.GetComponentsInParent<SMSAnchorContainer>(true);
           if (foundedAnchorContainer.Length < 1)
           {
               return id;
           }
           return $"{foundedAnchorContainer[0].fullID}_{id}_{(parent == null ? transform.GetSiblingIndex() : parent.GetSiblingIndex())}";
       }
   }

Пример получения конечного ИД для якоря.

Что дальше? Просто в активации объекта подписываемся на нужные события, как на обновления самой SMS, так и на работу режима администрирования.

protected async void OnEnable()
   {
       // auto update data from server
   MessageBroker.Default.Receive<SMSReloadMessage>().Subscribe(OnReload).AddTo(_cleanup);
      
       // events for admin mode
       _smsController
           .Mode
           .Subscribe(OnAdminModeUpdate)
           .AddTo(_cleanup);

       hover.HoverEvent += HoverOnHoverEvent;
       hover.HoverOutEvent += HoverOnHoverOutEvent;

       await Task.Yield();
      
       // work with view
       Show();
   }

Ну и самое последнее что нужно сделать – это отобразить саму SMS, если она есть в данном якоре.

 private async void Show()
   {
       var sms = await _smsStorage.GetByIdAsync(FullID);
       if (sms != null)
       {
           _smsButton = _smsButtonPool.Spawn(sms.ID, transform);
           _smsButtonID = sms.ID;
       }
   }

Для этого нужно достать из нашего хранилища SMS по ID, заспавнить из пула кнопку которая говорит о том что есть SMS и присвоить кнопке SMS.

Что мы получили на выходе? 

Данная система очень сильно облегчила совместную работу разработчиков и администраторов – перестал нарушаться запланированный темп работы из-за появления срочных задач на переделку контента SMS или расположения самой кнопки внутри приложения.

Рис 12. Roadmap развития нашего решения 
Рис 12. Roadmap развития нашего решения 

Это не означает, что наша система является полностью законченной, у нас в планах есть большой пласт работы над добавлением нового функционала и кастомизации режима администратирования. С каждым обновлением приложения все больше появляется новых элементов, экранов и блоков, и мы планируем в первую очередь добавить возможность администраторам самим из готовых инструментов просто и удобно создавать нужные им экраны, комбинации элементов отображения данных и работой с математической моделью расчетов. Но об этом, мы расскажем вам позже, как данная система будет готова и оправдает свои запросы :) Следите за нашими статьями!

Теги:
Хабы:
Всего голосов 3: ↑3 и ↓0+3
Комментарии0

Публикации

Истории

Работа

Ближайшие события