Всё не так просто с ctrl+z: об undo в быстром совместном редактировании

Случайно накосячили в документе, который вам только что пошарили? Драг-н-дропнули куда-то кусок чужого текста и не знаете, как жить дальше? Угодили курсором в ячейку вашего коллеги и уничтожили его данные? Ctrl+z не раз спасало наши жизни и репутации добропорядочных коллег, не портящих чужие (и свои) документы.

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


Undo в быстром режиме совместного редактирования появилось у нас вместе со сносками в версии 4.3. Больше о релизе вы можете узнать из нашей прошлой статьи (из этой статьи вы узнаете только об undo).

Быстрый, строгий, злой

Короткая справка о том, чем вообще отличаются режимы коэдитинга:

  • Быстрый. Вы видите, что печатает ваш соавтор. («Что за чепуху ты печатаешь, Николай?!)
  • Строгий. Вы спокойно работаете над своим куском текста, а правки соавтора видите только после сохранения. (»Что за чепуху ты напечатал, Геннадий?!")

Быстрый режим совместного редактирования включен в редакторах ONLYOFFICE по умолчанию. Раньше в нём не было undo.

Почему раньше в быстром режиме не было undo

Мы думали, что это опасно для документа. Допустим, Николай вставляет автофигуру, а Геннадий перетаскивает в нее часть текста из документа. Затем Николай отменяет действие, в результате чего удаляется автофигура. А с ней и часть текста, которую уже никак не вернуть. Геннадий и Николай грустно идут пить чай, обсуждая, как восстановить утраченный текст.

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

К undo, конечно же, нужно относиться осторожно (но на самом деле, вы рискуете уже просто когда шарите на кого-то документ с возможностью редактирования). Но мы расскажем вам, как всё устроено, чтобы минимизировать риски.

Google и мы

Нас постоянно спрашивают (на самом деле, спрашивают): Вы сделали это как у Google Docs? Нет.

Да, у них есть совместное редактирование и возможность сделать undo, и у нас эти вещи тоже есть. Но это не значит, что у нас внутри всё одинаково.

Как у Google. Документ находится на сервере, туда же отправляются все правки, там же собирается финальная версия документа. Например: Николай выделил какое-то слово жирненьким, а Геннадий курсивом. Оба два отправляют свои изменения на сервер, который уже разруливает этот конфуз: в частности, сообщает Николаю добавить курсив, а Геннадию сделать свой курсив жирным. В такой схеме ситуация, в которой один и тот же документ выглядит на разных клиентах по-разному, возможна (на очень короткий промежуток времени, конечно же).

Как у ONLYOFFICE. Если у Google ядро документа редактируется на сервере, то у нас всё это происходит на каждом клиенте. Сервер используется как база данных, в которой хранятся изменения. Как в такой схеме должны лечь изменения в ситуации, когда Николай выделил какое-то слово жирненьким, а Геннадий курсивом? Изменения лягут последовательно, при чем последовательность будет одна и та же на каждом клиенте. Ситуация, в которых у Николая и Геннадия документы выглядят по-разному в какой-то момент времени, невозможна.

Как это вообще связано с undo, спросите вы (на самом деле, мы понятия не имеем, спросите вы или нет, но представим как будто вы спросили). Из следующего пункта нашей истории вы поймете как.

Что происходит, когда вы нажимаете ctrl+z

Как мы уже сказали, в ONLYOFFICE все самые важные вещи происходят непосредственно на клиенте. Там же хранится список действий — не только своих, но и чужих. Свои собственные действия помечаются, чтобы потом была возможность их откатить.

И вот тут-то мы переходим к тому, как на самом деле происходит undo. Когда человек редактирует документ в одиночестве всё, в принципе, понятно. В блоке изменений хранятся действия одного человека и в случае необходимости мы просто берем последнее действие и производим антидействие. Блок действий при этом сокращается на единицу.

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

Рассмотрим простой пример. В документе содержится такой текст:

абв

Николай добавил в конце букву д и получил текст:

абвд

Увидев результат, Николай передумал и захотел отменить ввод буквы д. В это же время придирчивый Геннадий удалил букву б и в документе остался такой текст:

авд

Николай нажимает undo. Удаление и добавление текста происходит по позициям. Своим первым действием Николай добавил букву в позицию 3. В обычном редактировании undo сработало бы просто как удаление буквы из третьей позиции. Но ведь Геннадий уже постарался и удалил букву б из позиции 2 и буква д переместилась на её место. Таким образом в третьей позиции теперь просто пусто и удалять оттуда ну совсем нечего.

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

Если перенести действие Николая по добавлению буквы д в самый конец блока, то есть после того, как Геннадий злодейски удалил букву букву б из второй позиции, то получится, что Николай добавил букву Д в позицию 2. Делаем обратное действие — удаление из позиции 2. Undo проходит.

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

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

Ещё с undo, конечно, разные интересные проблемы, например

Неоткатываемые действия

Еще один простой пример:

1. Николай добавляет текст 12.
2. Геннадий удаляет 2.
3. Николай делает undo 2 раза.
4. Геннадий делает undo.

Итак, оба пользователя откатили все свои действия и у обоих не осталось ни одного undo в рукаве. Однако изначально пустой документ после отмены всех совершенных в нём действий пустым не остался. В нём гордо красуется цифра 2. Откатить её с помощью undo невозможно.

Исчезающие элементы

Рассмотрим ещё раз случай произошедший с Геннадием и Никлаем в начале статьи:

1. Николай добавляет автофигуру.
2. Геннадий набирает текст в автофигуре.
3. Нестабильный Николай делает undo автофигуры.
4. Вместе с автофигурой пропадает и текст, набранный Геннадием внутри неё. Окончательно.

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

Это не недостатки нашей реализации undo. Оно работает правильно. Оно будет идеальным, если вы с коллегами будете одновременно работать над разными объектами. И вот вам наше вам напутственное слово: будьте, как это сейчас модно говорить, mindful, работая с документами. Переключайтесь между режимами совместного редактирования и используйте undo с умом.
ссылка на оригинал статьи https://habrahabr.ru/post/327454/

UE4 для Unity-разработчиков

image

Привет, Хабр! Меня зовут Александр, и сегодня мы сравним Unity и Unreal Engine 4.

Думаю, многие разработчики пробовали движок Unity и видели сделанные на нём игры, проекты, какие-то демки. Его главный конкурент — движок Unreal Engine. Он берёт своё начало в проектах компании Epic Games, таких как шутер Unreal Tournament. Давайте рассмотрим, как начать работу с движком Unreal после Unity и какие препятствия могут подстерегать нас на пути.

Бывает, что 3D-движки сравнивают весьма поверхностно, либо акцентируют внимание только на одной из фич, например, на графике. Мы же холиварить не будем и рассмотрим оба движка в качестве равноправных инструментов. Наша цель — сопоставить две технологии и помочь вам разобраться в движке Unreal Engine 4. Сравним базовые системы движков на конкретных примерах кода демо-проекта UShooter (Unreal + Unity Shooter), специально сделанного для этих целей. Проект использует версию Unity 5.5.0 и Unreal Engine 4.14.3.

Система компонентов (Unity)

Когда мы запускаем проект на Unreal, то видим, что персонаж в сцене — лишь один объект. В окне World Outliner нет привычных нодов модели (вложенных объектов, мешей), костей скелета и т. д. Это следствие различий систем компонентов Unity и Unreal.

В Unity сцена состоит из объектов типа Game Object. Это пустой универсальный объект, к которому добавляются компоненты, реализованные скриптами поведения (MonoBehaviour) и встроенными компонентами движка. Иногда их оставляют пустыми, в качестве объекта-маркера, на месте которого будет создан, например, игровой персонаж или эффект.

Все эти объекты мы видим в окне Hierarchy в редакторе движка. Они имеют встроенный компонент Transform, с помощью которого мы можем управлять положением объекта в пространстве 3D-сцены. Например, скрипт движения объекта меняет координаты в функции Update, и объект двигается. Для добавления подобного скрипта на Game Object достаточно двух кликов. Создав объект — персонажа или предмет, — мы его настраиваем, добавляем скрипты и сохраняем в prefab (файл, хранящий Game Object и его дочерние объекты). Впоследствии мы можем менять сам prefab, и эти изменения отразятся на всех подобных объектах.

Вот как выглядит класс RocketProjectile, представляющий собой ракету в проекте UShooter.

Фрагмент RocketProjectile.cs

public class RocketProjectile: MonoBehaviour {     public float Damage = 10.0f;     public float FlySpeed = 10.0f;      void Update()     {         gameObject.transform.position += gameObject.transform.forward * FlySpeed * Time.deltaTime;     }      void OnCollisionEnter(Collision collision)     {         // Обработка столкновения     } }

Мы задаём параметры снаряда в редакторе, при желании меняем скорость перемещения (свойство FlySpeed) и урон (Damage). Обработка столкновений происходит в функции OnCollisionEnter. Unity сам её вызывает, так как на объекте есть компонент Rigid Body.

Система компонентов (UE4)

В Unreal Engine 4 игровые объекты представляются Actor’ами и их компонентами. AActor («актер») — это основной класс объекта, который помещается в сцене. Мы можем его создать в игровой сцене (как из редактора, так и кодом), менять его свойства и т. д. Также есть класс, от которого унаследованы все сущности движка: UObject.

image

Компоненты добавляются к Actor’у, игровому объекту. Это может быть оружие, персонаж, что угодно. Но эти компоненты условно скрыты от нас в аналоге Prefab’а — Blueprint Class.

В объекте Actor, в отличие от Unity, существует понятие Root Component. Это корневой компонент объекта, к которому крепятся остальные компоненты. В Unity достаточно мышкой перетащить объект, чтобы поменять у него иерархию вложенности. В Unreal это делается через привязку компонентов друг к другу ("attachment").

В Unity существуют функции Start, Update и LateUpdate для обновления или начала работы скриптов MonoBehaviour. Их аналоги в Unreal — функции BeginPlay и Tick у Actor’а. У компонентов Actor’а (UActorComponent) для этого существуют функции InitializeComponent и ComponentTick, поэтому нельзя «в один клик» сделать из компонента Actor, и наоборот. Также, в отличие от Unity, Transform есть не у всех компонентов, а только у USceneComponent и унаследованных от него.

В Unity мы можем практически в любом месте кода написать GameObject.Instantiate и получим созданный из Prefab’а объект. В Unreal же мы «просим» объект мира (UWorld) создать экземпляр объекта. Создание объекта называется в анриале спауном, от слова spawn. Для этого используется функция World->SpawnActor.

Персонажи и их Controller’ы

В Unreal для персонажей существуют специальные классы APawn и ACharacter, они унаследованы от класса AActor.

APawn — класс персонажа, которым может управлять игрок или AI. В Unreal для управления персонажами есть система контроллеров. Мы создаём Player Controller или AI Controller. Они получают команду управления от игрока или внутреннюю логику, если это AI, и передают команды движения самому классу персонажа, APawn или ACharacter.

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

Описание игрового класса (Actor’а)

Теперь, немного узнав о компонентах Unreal, мы можем взглянуть на класс ракеты в Unreal-версии UShooter.

Фрагмент RocketProjectile.h

UCLASS() class USHOOTER_API ARocketProjectile : public AActor {     GENERATED_BODY()  public:      // Sets default values for this actor's properties     ARocketProjectile();      // Called when the game starts or when spawned     virtual void BeginPlay() override;      // Called every frame     virtual void Tick( float DeltaSeconds ) override;      // Rocket fly speed     UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rocket")     float FlySpeed;      // Rocket damage     UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rocket")     float Damage;      // Impact (collsion) handling     UFUNCTION()     void OnImpact(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);  private:      /** Collision sphere */     UPROPERTY(VisibleDefaultsOnly, Category = "Projectile")     USphereComponent* CollisionComp; };

Взаимодействие редактора и скриптов, которое в Unity не требует специального кода, работает в Unreal через генерацию кода. Этот специальный код Unreal генерирует при сборке. Чтобы редактор мог показать свойства нашего объекта, мы делаем специальные обёртки: UCLASS, GENERATED_BODY и UPROPERTY. Также мы декорируем свойства и описываем, как редактор должен с ними работать. Например, EditDefaultsOnly означает, что мы можем изменить свойства только дефолтного объекта, blueprint class’а (prefab’а, если провести аналогию с Unity). Свойства могут быть сгруппированы в разные категории. Это позволяет быстрее найти интересующие нас свойства объекта.

Функция OnImpact — аналог OnCollisionEnter в Unity. Но для работы с ней требуется подписаться на события компонента USphereComponent в конструкторе или даже во время игры. Это не работает автоматически, как в Unity, зато здесь есть возможность оптимизации. Если нам больше не нужно реагировать на столкновения, мы можем отписаться от события.

Блупринты (Blueprint)

Типичное действие после создания C++ класса в Unreal — создание на его основе Blueprint Class’а. Это расширение объекта, которое нам предоставляет Unreal. Система Blueprint’ов в Unreal используется для визуального программирования. Мы можем создавать визуальные схемы, соединять события с какими-то реакциями на них. Через блупринты движок упрощает взаимодействие программистов и дизайнеров. Мы можем написать на С++ часть игровой логики и предоставить доступ к ней дизайнерам.

При этом Unreal позволяет отделить, если требуется, C++ исходники проекта от его бинарников и контента. Дизайнеры или аутсорсеры могут работать с собранными dll-библиотеками и никогда не узнают, что происходит внутри C++ части проекта. Это дополнительная степень свободы, предоставляемая движком.

image

Unreal хорош тем, что в нём практически всё связано с Blueprint’ами. Мы можем расширять ими С++ классы, создавать из них Blueprint-наследников и т. д. Эта система тесно связана со всеми компонентами движка, от его внутренней логики до визуальных компонентов, collision, анимации и т. д.

В Unity есть схожие системы визуального программирования, например Antares Universe. Они не входят в состав движка и созданы поверх него, поэтому в любой момент что-то может сломаться (например, при обновлении версии движка). Система визуального скриптования в Unity не предусмотрена. На мой взгляд, это серьёзный недостаток по сравнению с Unreal. Ведь благодаря таким системам даже далекие от программирования люди могут составить схему взаимодействия объектов или связать какую-то последовательность действий. К слову, в Unreal все шаблоны проектов имеют две версии: как на основе C++ кода, так и целиком на Blueprint’ах. Таким образом, создать простой проект без использования кода, целиком на блупринтах — вполне реально.

Демка шутера (UShooter)

В Unity мы пишем демку с нуля, а в Unreal опираемся на шаблоны. В шаблоне выберем управление и вид камеры, и Unreal сгенерирует проект с указанными настройками. Это хорошая основа, от которой вы можете отталкиваться для ускорения разработки и создания прототипа проекта.

image

Поверх шаблона Side Scroller мы добавляем собственный интерфейс (HUD), бочки, несколько видов оружия и звуки. Дадим игроку ракетницу и railgun, пусть героически стреляет по взрывающимся бочкам.

Система ввода (Unity)

Управлять персонажем будем с помощью системы ввода. В Unity мы обычно настраиваем ввод через Input Manager, создаём виртуальные именованные оси. Например, «идти вперёд» или «стрелять». Даём им имена и потом получаем значение какой-либо оси или состояние виртуальной кнопки. Обычно скрипты, которые занимаются управлением объектами, получают состояние осей в функции Update. В каждом кадре опрашивается состояние оси и целого ряда кнопок управления.

Система ввода (UE4)

image

В Unreal тоже есть виртуальные оси, но там есть разделение на собственно оси (значения, полученные от джойстика, и т.п.) и кнопки действия. В отличие от Unity, мы привязываем оси и кнопки к функциям класса, который реализует управление персонажем. Связь создаётся через компонент UInputComponent. Такой компонент ввода есть у класса персонажа ACharacter.

Вызовом BindAxis("MoveRight", this, &AUShooterCharacter::MoveRight) в Input Component мы привязываем нажатие кнопки MoveRight к вызову одноимённой функции движения. Не требуется каждый кадр заниматься опросом кнопки.

Также в Unreal не ограничено количество альтернативных кнопок. В Unity в Input Manager есть только основная кнопка и альтернативная. Чем больше устройств ввода в вашей игре, тем острее может быть эта проблема.

Работа с 3D-моделями

Как уже говорилось, в Unreal мы не видим в сцене структуру скелета персонажа. Дело в том, что компоненты скелета не являются Actor’ами или чем-то подобным. Это внутренние свойства скелета и анимации. Как тогда привязать к персонажу оружие или скрыть одну из его частей? Может, мы хотим надеть на него модную кепку или привязать оружие к руке.

В Unity мы выделим модель оружия в редакторе, перетащим в нужную кость, можем даже повесить на него отдельный скрипт управления. В Unreal мы будем пользоваться сокетами (Socket) — точками крепления на игровых объектах. Сокеты — это часть скелета в моделях со скелетной анимацией (в Unity такие модели называются Skinned Mesh, в Unreal’е — Skeletal Mesh). Также сокеты можно добавлять в статические меши (Static Mesh).

image

Выбираем кость, к которой крепится сокет, и задаём имя сокета, например S_Weapon, если к точке крепится оружие. После создания сокета можно создать («заспаунить») объект в позиции этого сокета или привязать его к сокету через механизм привязки (функции AttachTo). Система немного запутанная, в отличие от Unity, зато более универсальная. Мы можем один раз настроить названия точек, тем самым отделив игровую логику от настроек моделей. Причём если у нас имеется несколько моделей с одним скелетом, то сокеты надо будет добавить только в скелет. В демке шутера сокеты используются при создании снарядов и эффектов выстрела.

Система анимации (Unity)

У нас есть персонаж, мы знаем, как работать с вводом, теперь нужно проигрывать анимацию. В Unity для этого есть Animation Controller, в нём мы описываем определённые состояния персонажа. Например, бежать, прыгать или умереть. Каждому блоку соответствует свой анимационный клип, и мы настраиваем такой граф переходов:

image

Хотя эта схема называется Animation Controller, внутренней логики у неё нет. Это просто схема переключения анимации в зависимости от состояния. Чтобы она работала, мы заранее объявляем в этом контроллере названия переменных, соответствующих состоянию персонажа. Скрипт, управляющий анимацией, зачастую сам передаёт эти состояния контроллеру каждый кадр.

В переходах между состояниями (на схеме показаны стрелочками) мы настраиваем условия переходов. Можно настроить смешивание (crossfade) анимации, т. e. время, в течение которого одна анимация затухнет, а другая продолжится, для их плавного совмещения.

Система анимации (UE4)

В Unreal всё сделано Blueprint’ами, анимация не исключение. Создаём Animation Blueprint, который будет управлять анимацией. Он тоже представляет собой граф состояний. Так выглядит машина состояний, она управляет финальной анимацией персонажа в зависимости от движения или состояния смерти.

image

Тут мы видим уже знакомые нам состояния Idle/Run, Jump, Dead. Но один узел совмещает в себе Idle и Run. Внутри него находится так называемый Blend Space 1D, он используется для плавного перехода анимации в зависимости от значения одной или нескольких переменных. С помощью Blend Space можно привязать скорость персонажа к переходу между анимацией Idle и Run. Кроме того, получится настроить несколько точек перехода. Например, от нуля до метра в секунду персонаж идёт медленно — это будет движение, интерполированное между анимацией Idle и Walk. А после некоторого порогового значения включается бег (Run). И всё это будет в одном узле Animation Blueprint’а, который обращается к Blend State.

Стрелочками показаны переходы между состояниями, но, в отличие от Unity, мы можем создать Blueprint, реализующий внутреннюю логику работы этих переходов. В Animation Blueprint есть доступ к персонажу, на котором он используется, поэтому Blueprint сам обращается к его параметрам (скорость движения и т. п.). Это можно рассматривать как дополнительную оптимизацию, так как позволяет не рассчитывать параметры, которые не используются для текущего состояния персонажа.

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

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

image

В нижней части рисунка — фрагмент схемы Animation Blueprint, который отвечает за реакцию на выстрел из оружия. Команда Montage Play включает анимацию выстрела, затем Delay ждёт, пока она закончится, и анимация выключается командой Montage Stop. Так сделано, потому что в машине состояний анимации мы не можем задать однократное проигрывание анимационного клипа. Если анимация зациклена и соответствует какому-то состоянию персонажа, мы можем управлять анимацией через машину состояний. А если требуется проиграть один клип анимации по событию, то можем сделать через Montage.

Проблема вложенных Prefab’ов

Большая проблема в Unity — вложенные prefab’ы. На случай, если проблема вам не знакома, рассмотрим пример.

Предположим, объект «стол с ноутбуком» сохранили в prefab table1, а затем понадобился второй подобный объект, но уже с зелёным цветом экрана ноутбука. Создаём новый prefab — table2, перетаскиваем в него старый ноутбук, меняем цвет экрана на зелёный, сохраняем. В результате table2, второй prefab, становится совершенно новым объектом, у него нет никаких ссылок на оригинал. Если мы поменяем исходный префаб, это никак не отразится на втором префабе. Простейший случай, но даже он не поддерживается движком.

В Unreal, благодаря наследованию Blueprint’ов, такой проблемы нет: изменение исходного объекта отразится на всех дочерних объектах. Это пригодится не только для игровых объектов, персонажей, какой-то логики или даже статических объектов на сцене, но и для системы интерфейсов.

С другой стороны, можно попытаться победить эту проблему в Unity, используя ассеты в Asset Store. В Unity есть плагины, расширения движка, которые так и называются — Nested Prefabs. Существует несколько подобных систем, но они немного костыльные, сделаны поверх движка, поддержки нет. Они пытаются сохранить в себе внутреннее состояние объекта. Когда запускается игровая сцена, они пробуют восстановить внутренние структуры, их поля, свойства и т. д., удаляют устаревшие объекты в сцене и заменяют их экземплярами из префабов. В результате мы получаем не только удобство вложенных префабов, но и ненужные тормоза, лишнее копирование данных и создание объектов. А если что-то в движке поменяется, то эти системы могут и вовсе отвалиться по неизвестным причинам.

Системы UI

В Unity нельзя сохранить в prefab элементы окон или какие-то виджеты. Можем попытаться, но возникнет та же самая проблема префабов: движок забудет о старых объектах. Поэтому зачастую в Unity мы создаём элементы управления, добавляем скрипты и потом их копируем, не создавая prefab. Если приходится добавлять в такие «виджеты» что-то новое, требуемые изменения нужно повторять вручную.

В Unreal мы можем сохранить элементы интерфейса в виджеты (Widget Blueprint), быстро сделать на основе одних элементов управления новые. Cделали кнопку и надпись, пусть это будет наш status bar widget. На основе стандартных и новых виджетов получается быстро и удобно строить окна интерфейса. К слову, виджеты также расширяются за счет Blueprint’ов, можно описать логику их работы на визуальных схемах.

В Unreal система редактирования интерфейсов и всех виджетов открывается в отдельной вкладке редактора. В Unity интерфейс редактируется через специальный объект Canvas, расположенный прямо в 3D-сцене и зачастую даже мешающий её редактировать.

Преимущества и недостатки

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

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

Из плюсов Unreal стоит отметить визуальное программирование, наследование blueprint’ов, виджеты UI, систему анимации с множеством возможностей и многое другое. Кроме того, в Unreal Engine 4 существует целый набор классов и компонентов, рассчитанных на создание игр: Gameplay Framework. Gameplay Framework является частью движка, на нём созданы все шаблоны проектов. Классы Gameplay Framework открывают множество возможностей — от описания игровых режимов (Game Mode) и состояния игрока (Player State) до сохранения игры (Save Game) и управления персонажами (Player Controller). Особенная фича движка — продвинутая сетевая подсистема, выделенный (dedicated) сервер и возможность запуска сетевой игры в редакторе.

Заключение

Мы сравнили движки Unity 5 и Unreal Engine 4 на конкретных примерах и проблемах, с которыми вы можете столкнуться, начав работу с движком Unreal. Часть сложностей, присущих Unity, решена в Unreal Engine 4. Конечно, невозможно в одном докладе сделать всесторонний обзор этих технологий в полной мере. Однако мы надеемся, что данный материал поможет вам в изучении движка.

ссылка на оригинал статьи https://habrahabr.ru/post/327520/

Восстание машин: Как роботы захватили бухгалтерию

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



Кнопка — бэк-офис для предпринимателей. Ведём бухгалтерию, решаем юридические вопросы и забираем рутину.

В 2016 году разработчики Кнопки создали много роботов, всего их — 42. Это наши помощники, они забирают на себя рутину в работе бухгалтера: один распознаёт документы, второй их сортирует, третий проводит банковскую выписку. У каждого робота есть имя: Раскукожка, Сортировка, Проводник, есть даже робот Паникёр. Рассказываем, зачем нам помощники с искусственным интеллектом и как они работают.

Техническая вводная

Наши клиенты общаются с нами через веб-приложение или в мобильном приложении на Айфоне или Андроиде. Веб-приложение разработано на платформе .NET. Сначала была Java, но сейчас её почти не осталось. Недавно перенесли приложения в Azure.

Бухгалтеры ведут учёт тысячи клиентских баз в системе 1С. Для хранения баз используем технологию облачной системы 1сFresh, а многочисленные роботы живут кто где — часть в Azure, часть на наших серверах.

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

Рассказывает разработчик Кнопки. Почему перешли с Java на .NET:

1. Наше приложение в тот момент — это наследие, которое мы получили после 5 лет разработки. Оно создавалось без применения каких-либо инженерных практик. Структура кода и отсутствие его тестирования создавали гигантские трудности в написании новых фич. Чтобы сделать хоть какое-то даже небольшое изменение, мы тратили кучу сил и времени. Кроме того, приложение было спроектировано таким образом, что любые тесты приходилось очень долго и неудобно писать. Модульного тестирования не существовало. Были только интеграционные тесты, которые использовали живую базу. По итогу, все тесты проходили часами.

2. В силу того, что в приложении был один Enterprise и он погонял другой Enterprise, наше приложение очень долго разворачивалось и собиралось. Долго — это до 40 минут. Приходилось очень много времени, чтобы собрать и развернуть приложение после малейшего изменения или чтобы просто посмотреть на то, как выглядит какая-то фича на форме в вёрстке. Появлялись билд-хобби. 🙂

3. Стало очевидно, что новые фичи мы должны писать в отдельном приложении сбоку. Наших компетенций в .NET в тот момент стало сильно больше — у нас поменялась команда. Команда единогласно признавала, что язык C# намного приятнее Java. Кроме того, в .NET есть такие технологии как Linq, которые позволяют иметь дело не с настоящей базой, а с полноценной её InMemory реализацией.

4. Большая часть нашего приложения работает с 1С. И делаем мы это очень спорным способом через COM API, COM — работает только в Windows среде и .NET имеет нативную поддержку COM-а. То есть у нас всё равно было уже много кода на .NET, и команда видела, что этот код приятнее.

Как было до роботов

1С умеет готовить любую отчётность, но для этого нужно постоянно поддерживать актуальное состояние бухгалтерской базы. Кто-то должен завести в систему первичные документы, импортировать и провести банковскую выписку, создать и провести учётные документы. А ещё исправить ошибки, возникшие во время работы. Это важные задачи, но они занимают много времени.

Например, чтобы обработать банковскую выписку, по каждому платежу нужно определить, к какому виду операции он относится: оплата поставщику, возврат покупателю, снятие наличных, выдача займа контрагенту и так далее. Бухгалтер, зная особенности клиента, точно определит вид операции и правильно проведёт платёж в 1С.

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

Решили развивать машинное обучение и создать искусственный бухгалтерский интеллект, чтобы с его помощью автоматизировать ведение бухгалтерии. 90% всех бухгалтерских операций система будет выполнять сама, и лишь в 10% понадобится участие человека.

Как теперь

Андрей — владелец небольшой кофейни в Москве. Каждый день он закупает продукты у поставщиков, кормит москвичей отменной выпечкой и угощает кофе.

Учёт ведёт в iiko, а бухгалтерию доверяет Кнопке. Первичные документы аккуратно собирает и раз в неделю привозит к нам в Московский офис. Мы работаем с первичкой: сканируем, сортируем и отправляем контрагентам. Клиенту документы доступны в облаке, оригиналы храним в несгораемых шкафах, а сканы сразу попадают на конвейер документов.

Первым делом первичку Андрея мы сканируем и получаем pdf со всеми документами в одном файле. Чтобы разделить документы, в работу вступает робот Раскукожка. Он превращает пдфку в 150 джипегов.

Потом робот Сортировщик смотрит на каждый скан и понимает, какой из документов — акт, какой — УПД, а какой — товарная накладная. Он аккуратно сортирует их и кладёт в нужную папку.

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

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

Затем весь текст в документе распознаётся другим роботом. Он определяет название клиента, контрагента, дату, номер и всю фактурную часть. Для распознавания мы пользуемся решением от наших партнёров, которые, в свою очередь, используют софт ABBYY.

И только после этого скан попадает к бухгалтеру:

Бухгалтер проверяет и нажимает кнопку «Сохранить».

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

После этого бухгалтер проверяет все поступления и списания с расчётного счёта компании. Для этого нужна выписка с банковского счёта клиента. Раньше нам приходилось её запрашивать у всех клиентов.

Теперь всё проще. Чтобы получать выписку без участия клиента, мы интегрировались с Альфой, Точкой и Тинькофф банком. Клиентам не нужно заходить в интернет-банк, качать выписку и высылать её бухгалтеру. А в 1С всегда актуальная информация по платежам. Также выписка из этих банков отображается в клиентских приложениях. Остальные банки пока обслуживаются вручную.

Но просто скопировать платёж из банка в 1С недостаточно. Каждый платёж нужно правильно провести — и это тоже делает специальный робот. Для обучения использовались несколько сотен тысяч платежей, проведённых вручную.

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

В итоге, получили точность проведения выписки 97 % — это сравнимо с точностью человека.
Когда всё сделано и проверено, бухгалтер Ирина отправляет Андрею готовый отчёт и предварительную сумму налога. Андрей счастлив, заранее знает предварительную сумму налога и может её скорректировать. Как — подскажет бухгалтер.

Что всё это значит?

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

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

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

Мы считаем, это неплохо — зачем нам 5 миллионов бухгалтеров на население в 145 миллионов? Для сравнения, в США при населении в 300 миллионов насчитывается чуть больше миллиона бухгалтеров.

Мы верим, что в ближайшем будущем за счёт искусственного интеллекта качество бухгалтерского и налогового учёта вырастет в разы.

Благодарим за статью Максима Ахмадинурова (@movemind).
ссылка на оригинал статьи https://habrahabr.ru/post/327554/

Chinook: гонка инженеров за чистой энергией

В каждой школе есть свои клубы, начиная с вдумчивых шахматных поединков и заканчивая быстрыми забегами по полю в, например, футболе. А некоторые университеты связаны с Chinook. Это команда инженеров из Монреаля (Канада), которая проектирует, создает и гоняется на автомобилях с ветреной тягой. Мало того, что болиды невероятно быстры, так еще и вполне способы заново изобрести индустрию чистой энергии.

Когда впервые услышал о них, сразу подумал, что команда собралась отличная, — говорит Патрик Ролланд (Patrice Rolland), 25-летний студент Ecole de technologie superieure University и разработчик программного обеспечения Chinook.

Слово «чинук» происходит от названия ветра, который дует с восточных склонов Скалистых гор — это хребет в системе Кордильер Северной Америки. Ролланд трудится над устройством, которое будет таким же красивым, молниеносно-быстрым и напористым. Разработки в этой области намного важнее, чем просто золотая медаль за победу в очередной гонке. Происходит глобальное изменение климата, и «зеленая» энергия приобретает все большее значение.

То, что мы делаем, является сочетанием искусства, технологий и окружающей среды, — говорит Ролланд. — Мы должны расширить границы эффективности энергии.

Проектом Chinook занимаются только студенты. Их достижения уходят далеко за пределы учебных кабинетов. Команда уже контактирует с ВМС Нидерландов по поводу технологий, применяемых в болиде. Неплохо для студентов, которые «просто собирают механизмы по выходным», смеется Ролланд.

Работа над проектом начинается после окончания учебной недели. Команда собирается в гараже: на столе лежат печатные платы, на полу множество кабелей, помещение освещают ThinkPad, а из колонок звучит Dropkick Murphys. Все это создает веселую и полную энергии атмосферу, которая показывает страсть людей к своему делу.

Главное, что связывает команду — кроме похода в паб после работы, конечно, — тяга к технологиям. «Наши ThinkPad X1 Carbon работают как мозг машины. Мы установили сенсоры на автомобиль, и в режиме реального времени получаем нужные параметры. Можно быстро делать правки», — рассказывает Ролланд.

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

Команда думает не только над функциональными аспектами, вроде расположения колес и программного обеспечения. Ролланд делает еще и фишки ради веселья: «В этом году хочу сделать синхронизацию машины с аккаунтом в Twitter. Когда кто-то упомянет автомобиль, она свистнет. Очевидно, задача не первостепенная».

Гонка Aeolus проходит на побережье Северного моря. Организатором выступает голландская Ассоциация мероприятий ветряной энергии. Цель проста: добиться наилучших показателей эффективности по скорости относительно динамики ветра. В 2014 году команда Ролланда поставила мировой рекорд — 96,9%. Но с тех пор Германия захватила свое место на троне. Chinook стремится вернуть звание лучших.

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

В этом году Chinook ничто не должно помешать выигрышу Гран-При. Команда целиком изменила дизайн, начав с полностью новой механической системы и электронных компонентов.

Она очень обтекаемая; выглядит как фантастический суперкар, — объясняет Ролланд. — Аэродинамика улучшена, ПО обновлено. Мы подключим машину к Raspberry Pi, чтобы упростить разработку будущих апдейтов — поддержка Bluetooth и добавление веб-сервера для получения информации в реальном времени о механизмах и скорости ветра.

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

Ноутбук Lenovo ThinkPad X1 Carbon открывает новый уровень возможностей для работы и отдыха. Будучи исключительно легким и тонким, он не является ультрабуком в привычном понимании этого слова – это полноценный ноутбук в корпусе из углеродного волокна. Он весит всего 1,18 кг, и это лучший результат для 14-дюймового устройства на рынке. Более того, X1 Carbon отличается невероятной прочностью – его корпус прошел суровые проверки на устойчивость к экстремальным условиям (пыли, вибрации, жаре, холоду, высоте, влажности и даже к плесени). А аккумулятор обеспечит полный рабочий день автономной работы, и даже сверх того – до 11 часов.

Базовая конфигурация включает двухъядерный процессор Intel Core i5-6200U с частотой 2,3 ГГц, 4 ГБ оперативной памяти и SSD на 256 ГБ. Впрочем, процессор может быть и другим, а максимально возможный объем ОЗУ составляет 16 ГБ. Цена Lenovo ThinkPad X1 Carbon стартует с отметки 75 450 рублей.

Подробнее о ThinkPadX 1 Carbon: http://www3.lenovo.com/ru/ru/laptops/thinkpad/x-series/ThinkPad-X1-Carbon-4th-Gen/p/22TP2TXX14G
ссылка на оригинал статьи https://geektimes.ru/post/288542/

Чему меня научили игры 90-х

В последнее время я стал часто задумываться о том, почему при прочих равных стартовых условиях в детстве, мы становимся такими разными, когда взрослеем. Я имею в виду вопрос о том, как развивается наше восприятие мира. Мы учились по одним учебникам, ходили в одинаковой одежде. Наши родители были среднестатистическими врачами, учителями и продавцами. Школа, двор, спортивные секции и различные кружки и… В этой публикации я постараюсь рассказать об одном огромном пласте моего детства – игры Dendy. Рассказать о том, какую роль на меня оказало это чудо 90-х годов.

Dizzy – управление проектами

Мы брали картриджи с играми напрокат в салонах, оставляя в залог паспорта родителей. Чтобы стать счастливым обладателем популярной игры на сутки, надо было записаться в очередь, в бортовой журнал хозяина салона. Однажды, на почти пустой полке, я заметил непопулярный оранжевый бокс с надписью «Dizzy». И эта игра стала моей любимой. Благодаря ей я научился тому, чему меня не могли научить даже в школе.

Ваша задача собирать артефакты, менять их на другие вещи. Классический графический квест. Переносить вы можете только три вещи. Важен порядок переноса и обмена. Сохранения игр тогда не было. И каждый раз, начиная заново, надо было вспоминать, что и куда нести, порядок переноса. А это отнимало драгоценное время. Тогда я к своим школьным тетрадям добавил ещё одну и начал рисовать очерёдность сборки артефактов.

Руководители проектов, что вам это напоминает? Ни у кого среди моих знакомых не было такого подхода к прохождению данной игры.

До сих пор удивляюсь, почему некоторые мои сотрудники и коллеги не понимают простых вещей в планировании и управлении проектами. Игру я так и не прошёл. Всегда не хватало времени. Скачал пару лет назад эмулятор на ПК. Сейчас и сохраняться можно, и отец уже не выдернет вилку ч/б телевизора. Но пока так и не реализовал свою давнюю детскую мечту – собрать все звёзды в этой прекрасной игре. Может и к лучшему.

Чип и Дэйл — работа в команде

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

Лучше меня. Ты играешь внатяг, ты постоянно находишься в левом конце экрана. Не успеваешь за лидером. Он вперёд тебя собирает все жизни и наносит больше урона главному боссу. Начинаешь подмечать его ходы, прыжки. Постоянно учишься у него. И обязательно ищешь случая сесть с ним за соседний джойстик.

Хуже меня. Оставляешь ему жизни, ведь ты и так, с одной можешь всю игру пройти. Хватаешь его, несёшь и перепрыгиваешь сложные места. Показываешь ему безопасные места при битве с боссом.

Как я. Это самое интересное. Здесь мы придумали замечательный вариант. Нужно пройти до конца игры, при том пакостить друг другу. Хватать друг друга и кидать на врагов, при движении вверх по карте не дожидаться напарника и оставлять его в экранной пропасти. Здесь развивалась максимальная ловкость.

Именно тогда я осознал, что все люди разные и подход к ним должен быть индивидуальным, раз уж вам довелось играть в команде. Прошло много времени, теперь работая в команде и управляя людьми, я всегда подбираю индивидуальные методы работы с человеком и никогда не гребу под одну гребёнку. А теперь как вы думаете, с кем интереснее всего сотрудничать/работать в бизнесе, тот, кто хуже вас, лучше или как вы?

Race America – самоконтроль

Дожидаясь своей очереди у джойстика я, чтобы скоротать время, наблюдал не только за телевизором, но и за игроками. Вы, наверное, тоже замечали, что многие игроки, играя в различные гонки, двигались всем телом за виртуальной машиной/мотоциклом. Можно ещё сравнить с играющими пианистами. Смотришь на них и, кажется, что они проживают жизнь вместе с исполняемым произведением. Но у меня был другой подход. Я начал контролировать каждое своё движение. Удобная поза и никакой раскачки. Раскачка. В лёгкой атлетике в нас вдалбливали это правило. Движения из стороны в сторону при беге быть не должно — пустая трата энергии и неправильный поток мыслей. Позу монаха я принимал всегда, когда хотел быть лучшим игроком.

Вы слышали про невербальное общение? Люди вас постоянно читают и сами подают вам знаки. В любой стрессовой ситуации принимайте мою любимую позу — «гоночный монах». И тогда вы чаще будете выходить победителем после любых деловых переговоров. Просите повышения заработной платы, устраиваетесь на работу, увольняетесь, выслушиваете критику или сами критикуете — никакой раскачки.

Эпилог

После окончания школы я больше не играл в таких масштабах как в детстве. Будучи студентом чуть-чуть познакомился с Warсraft и ещё парой игр. А сейчас я вообще далёк от игровой индустрии. У меня растут собственные дети. Моя трёхлетняя дочь управляется со смартфоном лучше, чем её дед с кнопочным телефоном. Тот самый дед, мой папа, который говорил мне — «Не стреляй из электронного пистолета, посадишь кинескоп», но который втайне от мамы давал мне свой паспорт, чтобы я смог взять заветный картридж цвета солнца напрокат.

Я не знаю, напишет ли моя дочь когда-нибудь про то, чему её научили игры. Видит ли она в них то, что видел я, когда был маленьким, и что она видит кроме красочных спрайтов. Как бы ни было, но её порцию солнца я ей обязательно дам.

P.s.

У нас некоторые ребята курили с первого класса. Когда собирались у кого-нибудь на квартире поиграть, выстраивалась целая игровая очередь. А некоторым так курить хотелось, что приходилось пропускать свой шанс победить Толстосума. Я никогда в жизни не курил и не курю до сих пор. И вам не советую.
ссылка на оригинал статьи https://habrahabr.ru/post/327552/