Бесплатная альтернатива Unity: Urho3D + C# + Xamarin

от автора

Про Urho3D уже писали на хабре, это полностью открытый 3D движок на языке С++ с редактором и интересным набором 3rd parties: Box2D, Bullet, kNet и т.п. У движка есть редактор (написанный на нем же), но к сожалению, он далеко от Unity, зато есть другие плюсы (о них далее). Движок имеет очень аккуратный API, что стало причиной обращения взгляда Xamarin для использования кодогенератора (С++ API to C#) для генерации байндингов поверх API на языке C#. В результате получился движок (UrhoSharp) со следующими плюсами (по сравнению с тем же Unity):

  • Полная поддержка последней версии Mono 4.2.x, C# 6.0 с Xamarin Studio / Visual Studio — грубо говоря это обычное приложение с шаблонами проектов для Visual Studio
  • Полностью бесплатный и открытый код
  • Наличие C# (Xamarin) контролов, которые могут быть интегрированы в существующие неигровые приложения.
  • Все плюшки оригинального движка, описанные в большом списке тут.
  • Распространяется через Nuget который содержит базовые ассеты и native библиотеки что делает его легко подключаемым
  • Отличная производительность, минимальный оверхед от .NET/Mono


Эй, псс… не хочешь немного примеров?

Оригинальный Urho3D при помощи Emscripten запустили в WebGL, так что примеры можно глянуть даже через браузер, но работают они не шибко стабильно. Лучше посмотреть те же самые примеры на C# склонировав репозиторий и запустив на интересующей платформе. Примеры работают на всех основных платформах: Windows, Mac, iOS и Android. Несколько скриншотов примеров:

Ландшафт (карта высот) и вода:

Скелетная анимация:

Физика 3D (Bullet)

Физика 2D (Box2D)

Управление толпой (поиск пути для толпы):

Встраивание в существующие обычные Xamarin(Forms) приложения:

И многое другое (около 40 примеров, включая собственный от Xamarin) – копию игры ShootySkies.

Немного кода примеров:

Urho3D имеет типичную нодо-компонентную архитектуру. C# API практически копирует C++ код за исключением добавления сахара: свойств, событий, async/await. Вот так выглядет простейшая 3Д сцена:

public class HabraSample : Application {     protected override void Start()     {         // 3D scene with Octree         var scene = new Scene(Context);         scene.CreateComponent<Octree>();          // Box         var boxNode = scene.CreateChild();         boxNode.Position = new Vector3(x: 0, y: 0, z: 5);         boxNode.SetScale(2f);         boxNode.Rotation = new Quaternion(x: 60, y: 0, z: 30);         var boxModelComponent = boxNode.CreateComponent<StaticModel>();         boxModelComponent.SetMaterial(ResourceCache.GetMaterial("Materials/BoxMaterial.xml"));         boxModelComponent.Model = ResourceCache.GetModel("Models/BoxModel.mdl");          // Light         Node lightNode = scene.CreateChild(name: "light");         var lightComponent = lightNode.CreateComponent<Light>();         lightComponent.LightType = LightType.Point;         lightComponent.Range = 50;          // Camera         Node cameraNode = scene.CreateChild(name: "camera");         Camera cameraComponent = cameraNode.CreateComponent<Camera>();          // Viewport         Renderer.SetViewport(0, new Viewport(Context, scene, cameraComponent, null));     } } 

Из проекта CocosSharp были нагло скопированы отдолжены Actions которые позволяют строить красивые сложные анимации декларативно в стиле «поверни объект на столько градусов за столько секунд, затем передвинь его туда-то параллельно уменьшая размера». Выглядет это как-то так:

// уменьшить масштаб до 0.5 за 1 секунду игрового времени await boxNode.RunActionsAsync(new ScaleTo(duration: 1f, scale: 0.5f)); // передвинуть на новую позицию за 2 секунды await boxNode.RunActionsAsync(new MoveBy(duration: 2f, position: new Vector3(x: 5, y: 0, z: 0))); // перекрасить в желтый await boxNode.RunActionsAsync(new TintTo(duration: 1f, red: 1, green: 1, blue: 0)); 

Эти действия можно группировать, запускать параллельно и обромлять в easing functions.
В качестве примера:

boxNode.SetScale(0); // сделаем нулевой масштаб для ящика await boxNode.RunActionsAsync(new EaseBounceOut(new ScaleTo(duration: 1f, scale: 1))); await boxNode.RunActionsAsync(new RepeatForever( 	new RotateBy(duration: 1, deltaAngleX: 90, deltaAngleY: 0, deltaAngleZ: 0))); 

Что означает «увечить масштаб с 0 до 1 за 1 секунду используя EaseBounceOut easing. Затем начнем бесконечное вращение по оси Х 90 градусов за 1 секунду.

Генерация C# для C++ кода

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

  • Компилирование всего C++ кода в PCH файл (AllUrho.cpp)
  • При помощи проприетарной либки (враппер над Clang AST), которой скармливается этот PCH мы получаем дерево классов/членов (AST) С++ кода в виде managed объектов.
  • Генерируем DllImport для всех методов всех публичных классов (на этом этапе возникает много мелких нюансов). Но в целом проект генератора получился простой (не слишком красивый, т.к. писался в стиле «быстро-быстро и в продакшн»).

Таким образом обеспечивается покрытие около 100% публичного C++ API.

Репозиторий проекта и примеров можно найти на github.

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


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *