-
-
Save kkolyan/03de66729a6a8443ae935050c0687be3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Короче, под "я делаю что-то с использованием ООП" обычно называют это древнее нечто когда логику композируют путем наследования друг от друга классов с инкапсулированной логикой и данными, а также бесконечные слои абстракции. так делают, но получается мешанина, да. Поэтому и популярно мнение что ООП - фигня. | |
Но на самом деле, ООП не не обязательно использовать именно так. В умеренном использовании ООП очень даже полезно. Например для своих типов данных, контейнеров и других библиотечных случаев. Но не для дизайна игровой логики. | |
Юнити и C# не так уж и заточены под ООП. | |
C# достаточно хорошо поддерживает и лайтово-функциональный стиль и гибридно-процедурный. | |
А то, что предлагает Unity, это не столько ООП, сколько композитный подход. Идея архитектуры предлагаемой Unity в том, что игра состоит из абстрактный объектов (которые грубо говоря не имеют никаких свойств) к которым приаттачены компоненты, каждый из которых наделяет объект каким-то небольшим (в идеале) свойством. | |
Но делать игру с глубокой логикой чисто на композиции компонентов сложно. Лично я склонен считать что для сколь-либо сложных игр лучше использовать немного другой подход. | |
Во-первых, делим всю игру на слой симуляции и слой отображения. | |
Симуляцию в свою очередь делим на 2 части: | |
1.1. игровая модель данныех. это набор классов с одними только полями (можно делать только методы, которые не модифицируют состояние класса). Класс "Мир" с полями "монстры", "игровое поле", "очередь хода", "эффекты" и тому подобное. Критерий корректности - сериализация объекта "Мир" дает состояние сейв-файла. Здесь нет ничего об отображении - толкьо суть. Мир здесь описывается так, будто это реальный мир (пусть и со странными дсикретными клеточными правилами), а не чья-то игра. | |
1.2. поведение. это набор процедур, которые вызываясь каждый кадр пересчитывают состояние мира. Сдвигают летящие стрелы на "speed*Time.delta", декрементят кулдауны, обрабатывают отложенные в очередях события, реагируют на команды ввода (в терминах симуляции это решения принимаемые существами, а не какие-то там команды извне). | |
1.3. на самом деле, можно использовать классы и в классическом ООП стиле (приватные поля и методы, которые что-то делают умное), но очень важно это делать ТОЛЬКО для универсальных случаев - вектора, матрицы, контейнеры для особого индексирования. и каждый такой класс должен уметь делать только что-то одно. проверочный вопрос - "придется ли этот класс менять, если скопировать в другой проект в другом жанре?", и если ответ "да", то он сделан плохо и лучше расщепить его задачу на предыдущие два пункта. | |
(симуляция ничего не знает о Unity кроме векторной математики) | |
Отображение в свою очередь разделяется на 3 части: (а вот тут уже Unity полным ходом) | |
2.1. набор довольно простых и самодостаточных компонентов-MonoBehavior, которые так или иначе позволяют отображать данные из симуляции. Это куклы-марионетки и реквизит (а описанная выше игровая модель данныех - это сюжет спектакля). | |
2.2. набор процедур, которые выполняются каждый кадр и манипулируют состоянием сцены кукольного театра так, чтобы они соответствовали состоянию симулируемого мира. Это кукловоды. | |
2.3. обработка пользовательского ввода и передача команд в игровой мир. | |
На самом деле, то, что я описал отлично ложится на ECS (игровая модель (а в некоторых реализациях и модель сцены) = сущности+компоненты, а процедуры обоих словев - системы), но поначалу от ECS вы ничего не выиграете, только будете отвлекаться и писать лишний бойлерплейт. | |
А GoF-паттерны во многом устарели. Скорее для общего образования их стоит знать, но не как руководство к действию. Если у вас само по себе что-то получилось похожее на GoF - ок, вы теперь знаете как это называть, но не надо форсировать. | |
Понижение связности - полезная штука, но не нужно понимать ее как "прячте все за слоями абстракции". В игровой модели вообще на нее стоит забить - там гораздо важнее внятность. | |
При проектировании игры на чисто-композитном подходе (если игра очень неглубокая) - да, вот там можно и за интерфейсы друг от друга прятать разные компоненты, чтобы было легче сочетать разные компоненты друг с другом. Но в озвученной выше архитектуре компоненты сцены друг о друге знать и не должны - ими рулят процедуры-кукловоды | |
PS: В пошаговой игре очень значительная часть кода может быть вынесена из симуляции в отображение. Например упомянутый выше полет стрелы - это по большей части отображение. В игровой модели есть только факт выстрела и факт попадания (например, ивент, передаваемый из view в simulation, означающий что можно продолжать симуляцию). | |
PPS: В терминах упомянутого в треде MVVM, 1.1+1.2 - это Model, 2.1 - View, а 2.2 - ViewModel. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment