Про 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/
Добавить комментарий