Доклад будет рассказывать о современных подходах проектирования ПО. Основной темой будет построение компонентных архитектур на примере архитектуры сцены 3D движка. Будет рассмотрен классический объектно-ориентированный подход организации сцены, его плюсы и минусы, и в качестве альтернативы будет показан компонентно ориентированный подход организации сцены. Доклад позволит слушателям понять, как разрабатывать сложные системы, которые впоследствии можно легко поддерживать.
1 of 68
More Related Content
Wargaming.net: Архитектура современных 3D движков
1. Архитектура современных
3D движков
Vitaliy Borodovsky
Технический директор мобильного подразделения
Wargaming
3. Современные требования к технологии
• Хорошие инструменты для создания контента
• Конкурентноспособное качество всех модулей
движка
• Кросс платформенность
• Высокая производительность
• Поддержка целевого железа
• Гибкость и расширяемость
4. Хорошие инструменты для создания
к•онтента Высокое качество инструментов
• Требования растут с каждым днем
• Большой спектр инструментов
• Для художников
• Звуковиков
• Программистов
• и других
• Возможности работать над контентом паралельно
• Очень актуально для средних и больших комманд
• Возможность быстро увидеть результат
5. Расширяемость
• Гибкая и расширяемая архитектура
• Легкость поддержки своего кастомного кода
• Простота перехода на новые версии
• Удобная инфраструктура
• Интеграция с техническими сервисами
6. Кросс-платформенность
• PC
• Windows
• Mac OS
• Mobile
• iOS
• Android
• Windows Mobile
• Previous generation
consoles
• PS3
• XBox 360
• Current generation
consoles
• PS4
• XBox 1
7. Производительность и железо
• Огромное количество устройств в различных конфигурациях
• Производитель GPU
• Производитель CPU
• Операционная система и ее версия
• Выжать максимум из GPU
• Совершенно разные требования в зависимости от железа
• Различные API
• Выжать максимум из CPU
• Разные архитектуры, однако схожие проблемы
• Эффективное использование многоядерных процессоров
• Эффективная работа с памятью
8. Высокая сложность инженерных задач
Operation
Systems
Graphics APIs
CPU
Windows XP
DirectX 9
Hardware
ARM
x86
PPC
GPU
AMD
nVidia
Intel
SoC GPU
PowerVR
Mali
Adreno
Tegra
DirectX 11
OpenGL & ES
Metal
Mantle
PS4 API
DX 12
OpenGL 5
????
Windows 7,8
Windows 10
Mac OS X
iOS
Android
APIs
Windows Phone
* 3-7 поколений устройств каждого
из производителей
Координальные отличия
Требует поддержки нескольких версий
9. Конкурентноспособное качество
• Сложно добиться конкурентного качества на всех
платформах
• Для конкуренции на различных платформах
требуются разные технологии
• Разные платформы требуют различный
оптимизаций
• Однако есть части которые требуются на всех
платформах
11. Проблемы универсального движка
• Выбор общего знаменателя
• Всегда будет ситуация когда выбор технического
решения будет сделан в ущерб какой-небудь из
платформ
• Универсальный движок всегда хуже движка под
конкретную игру
• Платформы обновляются быстро
• В универсальный движках, часто не хватает новых
специфических фич платформы
12. U•nity Обладает массой свойств которые требуются современному
движку, но есть минусы:
• C# - создает дополнительные накладные расходы
• Нет прямого доступа к железу
• Не возможно выжать максимум из целевого железа
• Отлично подходит для казуальных игр
• Не подходит для игр, которые требуют выжать максимум из
железа
• Всегда найдутся команды, которые смогут получить
конкурентное преимущество используя железо по максимуму,
на своей технологии.
• Игра - это всегда совокупность идеи и технологии!
13. UE4
• Очень многообещающе
• C++ и полный доступ к исходникам
• Дает разработчикам полный контроль
• Отличные инструменты
• Минусы
• Основные цели это новые консоли, решения принимаются не в пользу
мобильных технологий
• 5% royalty from gross revenue
• Может быть большой процент от прибыли
• Особенно для инди разработчиков
• Часть решений основаны на предыдущем опыте, не идеальном в
случае UE3
14. Плата за быструю разработку
• Использование скриптовых языков или JIT компилируемых языков
• Быстрая итерация
• Меньше требования к разработчикам и скриптерам
• Хорошо на этапе прототипирования, плохо в долгосрочной перспективе
когда эти люди пишут реальный игровой код
• Больше нагрузка на CPU
• Меньше возможностей по выжиманию производительности из целевого
железа
• Некачественный код
• Критично на мобильных платформах
16. В 2011 году
• Не было мобильных движков консольного качества
• Unity не позволял делать то что требовалось проекту
• Мы имели достаточно неплохую технологию, которая доказала
себя на казуальных играх
• Было принято решение доделывать свой движок
• Учитывая что 3D не было, это было 95% работы
• Сроки были сжатые
• 1-ю версию движка и редактора сделали за 2 месяца
• На первоначальном этапе разработки не всегда
принимались взвешенные архитектурные решения
18. Tools (2011-2012)
• Большая архитектурная ошибка
• Использовать игровой UI для
редакторов
• Не было undo-redo
• Каждая ошибка дизайнеров
требовала загрузить карту заново
• Не было copy-paste
• Не было переключений между
элементами по табу
• Художники с тех пор стали очень
осторожными и терпеливыми!
20. Философия
• Использование современных подходов к
проектированию архитектуры
• Тчательный выбор технологий
• Data-driven подход
• Рефакторинг
• Кросс-платформенный подход
21. Выбор основных технологий
• C++
• Высокая производительность
• Высокая портабельность
• Qt для разработки Tools
• Современная кросс-платформенная технология
• Много примеров высококачественного софта
• Движок может напрямую работать с UI
• WinForms - требуется прослойка на C#, для
движка
22. Cross-platform
• Main focus is iOS & Android
• Support from low-end to high-end mobile devices
• PC & Mac
• Focus on support of low-end PC & Mac with
embedded video cards
• Big market
• Maximum usage of the hardware
23. Плюсы
• Полный контроль и максимальная гибкость
• Возможность менять ее в зависимости от платформ и требований
• План развития который соответствует планам наших проектов
• При правильном подходе
• Возможность использовать по максимуму целевое железо
• Конкурентное преимущество
• Практически у всех разработчиков под консоли, свои технологии,
по этой причине
• Возможность быстрее итерировать
• Не нужно ждать когда выпустят новую версию движка, мы
получаем ее раз в месяц
24. Минусы
• Титанический объем работы!
• Очень высокие требования к команде
разработчиков.
26. Tools
• Художникам нужны хорошие инструменты создания
контента
• Отдельных инструментов становится все больше и
больше
• Фичей в движке с каждым днем становится все
больше и больше
• Как можно эффективно разрабатывать, при
небольшом количестве программистов на тулзах?
• Data-driven UI
28. Data-driven UI
• Reflection / Introspection
• UI генерируется исходя
из типов данных которые
присутствуют в объекте
• Поддержка иерархий
объектов
• Динамическая
интроспекция
• Различные варианты
представление
одинаковых типов
данных
30. Рендер система
• Низкоуровневая система
• Разные API
• C разными возможностями
• Разными сложностями
• Высокоуровневая система
• Огромное количество алгоритмов
• Часто очень непохожие друг на друга по принципам и
требованиям к данным
• Решение есть
31. Сцена - рассмотрим на примере
• Комбинация множества сложных систем
• Рендеринг
• Физика
• Коллизии
• Анимации
• Отсечение невидимой геометрии
• Лоды
• Скрипты
• Пользовательская логика
• и многое другое
32. Граф сцены
• ООП подход
• Полиморфизм
• Базовый класс
• Наследники
SceneNode
RenderNode
LODNode
OtherNode
Matrix4 localTransform;
Matrix4 worldTransform;
Vector<SceneNode*>children;
virtual void Update()
virtual void Draw()
Вроде все просто?
Не так уж и просто!
33. Объектно-ориентированное
пр•оЧгтроа тмакмоие рОоОвПание
• a programming paradigm that uses "objects" – data
structures consisting of datafields and methods
together with their interactions – to design applications
and computer programs. (Wikipedia)
• Includes features such as
• Абстракция данных
• Инкапсуляция
• Полиморфизм
• – Inheritance
34. Для чего нужно ООП
• ОО программирование позволяет думать о
проблемах в терминах объектов и их
взаимодействий
• Каждый объект в идеале самодостаточен
• Содержит в себе свои данные и код
• Предоставляет интерфейс для взаимодействия
• Каждый объект может быть представлен как black
box
35. Объекты
• Если объекты самодостаточны
• Они могут быть повторно использованы
• Они могут быть изменены, без влияния на
внешнюю среду
• Использованы без понимания их внутренней
структуры
• Это ведь хорошо, да?
37. C++
• Выпущен в 1979
• Стандартизирован в 1998
• Новый стандарт в 2003 и 2011
• За это время, произошло множество изменений:
• С++ претерпел значительные изменения
• CPU стали намного быстрее
• Память тоже стала быстрее
• Появились многоядерные процессоры
40. Что изменилось с 1979?
• 1980 - RAM latency - 1 цикл
• 2010 - RAM latency - 400 циклов * 2 - 4 ядра
• 2014 - RAM latency - 400-600 cycles * 4-8 ядра
• Что можно сделать за 400-600 циклов?
41. На современном железе
• Инкапсуляция данных это очень плохо!
• Производительность может быть увеличена в разы,
при другом подходе к данным
• Железо диктует органичения, но само ООП, это
же отличная парадигма, да?
43. Проблемы ООП подхода
• Наследование и полиморфизм
• Код написанный в объекте, влияет на всех его
потомков
• Высокая связность
• Разнородный код, выполняется вперемешку
• virtual Update(), virtual Draw(), virtual Anything()…
• Сложно эффективно использовать многопоточность
• С++ статический язык
44. Немного усложним
BaseNode
JointNode
PhysicalNode
CollisionNode
RenderNode
ContainerNode
LODNode
SwitchNode
SoundNode
VehicleNode
ScriptNode
SkinnedNode
• Как наследовать классы и не
ошибиться?
• Есть классы которые просятся
ниже
• AnimationNode - любой
объект, может быть
анимированным
• Physics, Collision, Script
AnimationNode аналогично
TransformNode
47. В• цОибфхорд а50х00 тысяч нод, без трансформаций (8 ms на iPad
2)
• if (flags & NODE_REQUIRE_UPDATE)return;
• Обход 11,111 объектов, без трансформаций (4ms на
PS3)
• Почему
• Неэффективное использование кэша
• В среднем 2-4 кэш мисса, при переходе к следующему
объекту
• Обращение к vtbl, обращение к flags
• Быстрое переполнение кэша
48. Поддержка ООП кода
• Любое изменение в базовом классе требует полное
тестирование всего движка
• Чем сложнее система, тем больше объем работы,
при малейшем изменении
• Виртуальные функции влияющие на потомков,
являются постоянным источником проблем
• Для сложных игровых систем
• Наследники могут ломать логику оригинальных
классов
• Влияние классов друг на друга значительно
49. Другие подходы
• Data-driven paradigm - in which the program statements describe
the data to be matched and the processing required rather than
defining a sequence of steps to be taken.
• Оперируем над однородными данными
• Алгоритмы преобразовывают входные данные в выходные
данные
• Component-based paradigm
• It is a reuse-based approach to defining, implementing and
composing loosely coupled independent components into
systems.
• Слабосвязные компоненты
• Пример: unix tools, промышленная электроника
50. Data-driven подход к той же проблеме
• Есть данные
• TransformComponent
• RenderComponent
• LODComponent
• PhysicsComponent
• и др.
• Для каждого однотипного массива данных мы выполняем необходимые
операции
• For each transform in transformComponentArray
• Perform Transform
• For each renderComponent in renderComponentArray
• Call Render
51. Что мы получаем
• Независимые потоки выполнения подсистем
• Слабая связность
• Легко оптимизировать
• Легко разложить на многоядерные процессоры
• Можно расположить данные для подсистем
линейно, в удобном для них виде
• Как связать компоненты воедино?
52. Entity
• Entity - сущность
• Только ID
• Список принадлежащих этой entity компонентов
53. Г•деКо пд ив скоамтпьо нкеонтда?х
• virtual void
Component::Process()
• Гибко, и красиво, но мы
попадаем в ту же ловушку
наследования
• Появляются разнородные
данные, обрабатываемые
через одинаковые классы.
• Проблема меньше чем с мега-
классом, но все еще не идеал
• Код должен быть отдельно!
55. Реальный пример
Components
Render
Transform
Collision
Physics
Animation
Script
Sound
Particle
More
Systems
Render Update System - update render system with info from others
TransformSystem - perform transformations
CollisionSystem - perform collisions
Physics - calculate physics
AnimationSystem - system to transform animations
ScriptSystem - system to perform scripts
SoundUpdateSystem - update positions from world to sound engine
ParticleUpdateSystem - update particle systems
UpdateSystem, OcclusionSystem, CullingSystem and many others
56. Плюсы
• Легко добавлять новую функциональность
• Слабая связность, помогает реже ломать
написанный код
• Нет потока кода (логики), который управляет
программой, тоже приводит к большей стабильности
кода при изменениях
• Можно легко параллелить на несколько ядер
• Позволяет расположить данные линейно
• Системы могут перекладывать данные таким образом
как им это удобно
58. Сложные случаи
Components
TransformComponent
LookAtComponent
Entity1
Systems
TransformSystem
LookAtSystem
TransformComponent
Entity2
LookAtComponent
Entity3
TransformComponent
Entity4
LookAtComponent
59. Сложные случаи
Components
TransformComponent
LookAtComponent
Entity1
Systems
TransformSystem
LookAtSystem
TransformComponent
Entity2
LookAtComponent
Entity3
TransformComponent
Entity4
LookAtComponent
60. Сложные случаи
Components
TransformComponent
LookAtComponent
Entity1
Systems
TransformSystem
LookAtSystem
TransformComponent
Entity2
LookAtComponent
Entity3
TransformComponent
Entity4
LookAtComponent
61. Как решать
• Dependency Manager
• Определяет зависимости между компонентами, группирует их в
списки, вызывает Process системам в правильном порядке
• Красиво, но сложно.
• TransformComponent, LookAtComponent - оба работают с одними
данными
• Могут быть частью одной TransformSystem-ы
• Связывает все в одну систему.
• Зависимость между системами
• LookAtSystem вызывает Process для TransformSystem
• Просто в реализации
65. Баланс это сложно
• Старайтесь найти время на переработку архитектуры
• Если в порядке архитектура, это откроет новые возможности в
будущем
• Не обязательно делать все сразу
• Итеративный подход понимая где ваша цель
• Анализ того что вы получите по итогу
• Наш переход от SceneGraph к Entity Component System был
болезненным
• Мы не смогли все сделать сразу, ввиду сроков по проекту
• Не смогли сделать JOB-ы и multithreading
• Помните, что заложив правильный фундамент, кирпичи можно
положить потом
67. Launcher
• Similar to Tanks Game Launcher
• List of tools with latest versions
• Stable versions updated automatically
• Artists are happy! Because they always have latest
version.
Чем сложнее система, тем сложнее поддерживать и тестировать
С ростом сложности систем часто есть желание опустить класс на уровень ниже
Или все полиморфно, или каждый класс при использовании намертво связывает тот кусок кода в котором он используется