Привет Хабр!

На прошлой неделе, после релизов версии 2020.1, для всех наших десктопных продуктов случилось еще одно большое событие — мы открыли публичный доступ к пробной версии Rider for Unreal Engine. На данный момент это отдельный продукт, версия нашей среды для разработки Rider, но с поддержкой C++ и Unreal Engine.

Rider for Unreal Engine

Так, стоп! Среда разработки на C++. Еще одна?! Давайте разбираться по порядку.

Начнем с небольшой истории. Несколько лет назад мы собрали всех, кто в JetBrains делает инструменты для C++, чтобы обсудить, насколько пользователям тяжело ориентироваться в многообразии наших предложений. Ведь есть и CLion, и ReSharper C++, и поддержка для C++ в AppCode. Через несколько часов обсуждений пришли к таким выводам:

  • Хотя универсальный инструмент и выглядит заманчиво, при расширении таргетинга, увеличении количества интегрированных сторонних инструментов, поддерживаемых случаев использования становится очень сложно искать баланс между удобством, интуитивностью интерфейса и обилием возможностей.
  • Мир разработки ПО уже давно не имеет четких границ по языкам разработки. Многие проекты мультиязыковые. Важнее — область применения ПО и технологии, которые в ней используются.

В итоге, мы решили унифицировать пользовательский опыт в наших инструментах для C++, но сошлись на том, что подход делать разные инструменты (пусть и с общим ядром или на общей платформе) для разных областей разработки ПО — правильный. На практике это выглядит следующим образом:

  • CLion — наше основное предложение для разработки на C и C++. Кроссплатформенная среда разработки ориентируется на нативную разработку, проекты финансового сектора, встроенную разработку, проекты AI, разработку библиотек, утилит и пр. При этом существующие ограничения на тулчейны и, особенно, проектные модели (поддерживается CMake, Gradle Native, compilation database, существует плагин для Bazel, в разработке находится поддержка Makefiles) являются скорее техническими. Проще говоря, мы не видим проблем с тем, чтобы в CLion появилась поддержка того же msbuild, если это нужно нашим пользователям, но ее сейчас попросту некому делать.
  • ReSharper C++ — выбор тех, кто занимается именно разработкой на Windows, в специфическом стеке инструментов, и кто не готов отказаться от Visual Studio. Зачастую эти люди еще и комбинируют разработку на C++ и на C#. Этим разработчикам мы предлагаем расширение для Visual Studio, версию широко известного нашего продукта ReSharper, но для C++.
  • AppCode — вообще отдельная история, так как это среда для разработчиков под iOS/macOS. C/C++ тут скорее часть общего mac-специфичного стека разработки.

Так, а при чем тут Rider? Какое отношение к C++ может иметь кроссплатформенная среда для разработки на .NET? На практике, около 30% пользователей Rider — это игровые студии и компании по разработке игр. Оно и понятно, ведь Rider во многом популярен именно как среда для разработки под Unity. Уже не первый год команда Rider кастомизирует инструмент именно под этот игровой движок. Результат нравится не только программистам под Unity, но и самим Unity Technologies, с которыми мы давно и плодотворно взаимодействуем по части самой технологии.

Заходя ко многим нашим пользователям из области разработки игр, мы заметили, что у многих студий нет четкого разделения — делать игры только на Unity или только на Unreal Engine. Сегодня у них игра на одной технологии, а завтра — на другой, или одна команда использует Unreal Engine, а другая Unity или вообще свой кастомный движок. При этом понятно, что разработчикам и компаниям в целом очень не нравится “прыгать” между разными средами разработки. И вот тут-то мы и решили, что, если мы смогли сделать Rider успешным для Unity, то мы можем пойти дальше и сделать его успешным в целом для мира игровой разработки. Так родилась идея Rider как универсальной среды разработки для Game Dev.

Из чего состоит Rider for Unreal Engine


Дальнейшее развитие событий довольно очевидно для тех, кто знаком с технологией, на которой построен Rider. Rider состоит из front-end части на базе платформы IntelliJ и back-end части на базе ReSharper. Все языковая поддержка работает на back-end. Поэтому мы просто подключили уже имеющуюся в ReSharper C++ поддержку C++ и Unreal Engine к Rider по той же технологии. Из специфичного пришлось дополнительно реализовать:

  • Плагин для выбора Rider как среды разработки в Unreal Editor (Rider Source Code Access) для версий движка 4.22-4.24. Начиная с версии 4.25 эта функциональность уже будет включена в сам движок UE.
  • Плагины UnrealLink для Rider и RiderLink для Unreal Editor, которые обеспечивают интеграцию с Blueprints в Rider и в целом отвечают за коммуникацию между Rider и Unreal Editor.
  • Отладчик.

Стоит отметить, что сейчас превью Rider for Unreal Engine доступно только на Windows, открывает файлы .sln и полагается на сборку компилятором от Microsoft. В будущем, к моменту релиза, мы постараемся расшириться до всех трех платформ и реализовать поддержку .uproject как основной проектной модели.

Отладчик на основе LLDB


Значительная часть разработки игр происходит сейчас на платформе Windows и в рамках тулчейна от Microsoft. Если посмотреть на то, какие инструменты для отладки существуют для кода, который скомпилирован с помощью компилятора Microsoft Visual C++, то мы увидим:

  1. В своих собственных инструментах Microsoft использует инструменты отладки на основе vsdebugeng.dll. Лицензия не позволяет использовать эти инструменты в сторонних средах разработки.
  2. CDB и WinDbg используют dbgeng.dll. И именно этот вариант мы изначально пробовали для написания своего отладчика для MS стека. Но столкнулись с плохой производительностью на больших бинарных файлах с большим количеством файлов символов (.pdb), и, что еще более важно, с частым аварийным завершением приложения.
  3. Существовали также наработки в LLVM-сообществе по поддержке отладки для тулчейна Visual Studio с помощью LLDB. Ими мы и воспользовались, и буквально года за полтора написали первую версию в общем-то работающего отладчика. Он включает начальную и еще пока сырую поддержку формата NatVis (такие MS-специфичные pretty printers). При этом сейчас Rider for Unreal Engine сам находит NatVis-ы в проекте на Unreal Engine и подгружает их отладчику. Этот же отладчик мы сейчас используем в CLion для тулчейна Visual Studio (он включен по умолчанию в этом случае начиная с версии 2020.1).

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

Поддержка C++


Повторю — вся функциональность языковой поддержки из ReSharper C++ теперь доступна в Rider for Unreal Engine Preview. Она включает:

  • Около 170 различных инспекций кода и более 50 быстрых исправлений.
  • Рефакторинги, учитывающие все контекстные использования символа (переименование, изменение сигнатуры метода, вынос метода, добавление поля / переменной / typedef, подстановка (Inline) переменной или typedef, и другие).
  • Генерация кода (методы getters/setters, конструкторы, операторы сравнения, шаблоны документации кода).
  • Действия для помощи в написании кода, навигация, форматирование и поддержка стилей именования, сортировка #include директив.

Generate action

Поддержка HLSL, C#, диалектов uproject/uplugin


В этом году мы начали работать над поддержкой языка для написания шейдеров HLSL в ReSharper C++, и она сразу попала и в раннее превью Rider for Unreal Engine. Поддержка включает в себя подсветку синтаксиса, тултипы с документацией, подсказки имен параметров и типов, действия навигации, автодополнение, поддержка виртуальных путей файлов, и даже рефакторинги.

Так как в основе Rider for Unreal Engine среда для разработки на .NET, то языковая поддержка работает и в файлах Build.cs, и в Target.cs.

И наконец, если говорить о поддержке языковых диалектов, Rider for Unreal Engine понимает диалекты файлов .uproject/.uplugin, предоставляя опции автодополнения и тултипов документации.

uproject dialect

Интеграция с Blueprints


Файлы Blueprints представляют собой данные в бинарном формате, редактирование которых происходит как правило в визуальном редакторе внутри Unreal Editor. Объекты в этих файлах наследуются от классов на C++, переопределяют проперти из C++ части игры. И вот тут Rider for Unreal Engine является той уникальной средой разработки, которая зачитывает все необходимые файлы Blueprints и показывает эти связи в редакторе кода на C++:

BP derived classes

При этом, если поменять, например, значение свойства в редакторе Unreal Engine и сохранить asset, то значение тут же автоматически обновится и в Rider (у нас повешены watchers на изменение asset-файлов):

BP properties

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

Вызов поиска использований (Find usages) включает не только использования в коде на C++, но и в файлах Blueprints. Двойной клик по таким использованиям открывает Unreal Editor.

Понимание механизма рефлексии UE4


Рефлексия в Unreal Engine реализована с помощью специальных макросов (UCLASS, UFUNCTION, UPROPERTY и др). Rider знает, что параметры таких макросов — это не просто текст. Парсер языка C++ в ReSharper C++ и Rider умеет действительно “понимать” значение этих макросов, даже не запуская Unreal Header Build tool (то есть еще до того, как реально сгенерируется содержимое файлов .generated.h).

Кстати, говоря про файлы .generated.h, ReSharper C++ и Rider знают, что автоматически добавляемые пропущенные директивы #include надо вставлять строго до подключения файлов .generated.h. А также учитывают эти генерируемые файлы в рефакторингах переименования.

Возвращаясь к механизму рефлексии, стоит сказать, что спецификаторы рефлексии — это в ReSharper C++ и Rider тоже не просто текст. Для них есть автодополнение и подсказки документации:

Reflection doc

Подсказки документации доступны и для самих макросов рефлексии.

А еще анализатор кода проверяет использование макросов рефлексии и указывает на связанные с этим ошибки. Например:

  • Классы UCLASS должны быть публично унаследованы от UObject или любого его класса наследника. При этом такой родитель должнен быть ровно один.
  • Спецификаторы UCLASS должны быть использованы для классов, USTRUCT – для структур.
  • Классы UE4 не могут быть объявлены внутри других классов.
  • Объекты, сохраненные в полях, не отмеченных UPROPERTY, могут быть собраны сборщиком мусора в любое время.

Поддержка вызовов удаленных процедур (RPC) в действиях навигации и генерации кода


Если рассматривать вызовы удаленных процедур с точки зрения обычного парсера C++, то довольно быстро можно заметить неосведомленность парсера о том, что объявлению функции может соответствовать несколько имлементаций с отличающимися именами (например, суффиксами _Validate и _Implementation). В ReSharper C++/Rider мы обучили парсер идентифицировать RPC по спецификаторам Client, Server и NetMulticast в параметрах макроса UFUNCTION. Благодаря этому:

  • В навигации предлагаются все необходимые варианты имплементации функции.
  • Генерация кода умеет создавать функции с суффиксами _Validate и _Implementation или только те из них, которые отсутствуют:
    RPC generation
  • Рефакторинги кода Rename и Change Signature обновят все необходимые функции и тем самым сохранят ваш код в корректном состоянии.

Знание правил именования Unreal Engine 4


ReSharper C++ и Rider осведомлены об официальных правилах именования в коде Unreal Engine. Эти правила используются средой разработки во всех действиях по работе с кодом, вроде генерации getters и setters или рефакторинге добавления переменной (Introduce Variable). А главное, что существует проверка кода Inconsistent UE4 naming inspections и соответствующее быстрое исправление, которое вызовет рефакторинг Rename и переименует все использования имени, не соответствующего правилам.

Производительность редактора


Мы довольно давно делаем поддержку разработки на Unreal Engine в ReSharper C++ и, конечно, видим, что производительность редактора является основной жалобой. Rider в силу особенностей архитектуры избавлен от многих проблем с производительностью, которые присутствуют в ReSharper (там они есть отчасти из-за ограничений студии на 32-разрядные процессы, в рамках которых происходит работа ReSharper, но не только).

Помимо этого, мы специально настраиваем работу IDE для улучшения производительности на Unreal Engine. Мы сначала индексируем код пользовательской игры, мгновенно включая все умные действия редактора на пользовательском коде. А индексация уже кода самого движка происходит после этого в фоне. Есть и еще несколько дополнительных опций по управлению индексацией:

Performance options

В результате, те, кто уже начал пользоваться Rider for Unreal Engine, отзываются о производительности редактора очень положительно! А мы уверены, что можем сделать еще лучше.

Видеодемо и еще раз о том, как получить доступ


Эти и многие другие возможности можно посмотреть в действии в демо-ролике (на английском) от нашего девелопер-адвоката:


А чтобы попробовать эти возможности самостоятельно, достаточно заполнить простую форму и получить от нас письмо со ссылкой на билд и активацию бесплатной лицензии на раннее превью. Переходите, заполняйте, пробуйте, пишите отзывы! Для ваших отзывов, как обычно, есть комментарии тут, трекер (ReSharper C++ и Rider) и почта нашей поддержки (rider-cpp-support@jetbrains.com).

Спасибо за внимание!

Команда Rider
The Drive to Develop