Как лучше организовать архитектуру проекта в Unity?

Я сейчас делаю один проект на Unity. Вкратце, это игра про космос, где игрок управляет планетой, которая "вращается" вокруг своей звезды и защищает её от разных опасностей.

У меня в проекте есть абстрактный класс AbstractMovementSystem, от которого наследуются классы PlanetMovementSystem и MoveToTargetSystem. Сделано это потому, что в вышеуказанных классах всё равно был бы метод Move и поля _maxSpeed и _currentSpeed, а создание абстрактного класса позволяет соблюдать принцип DRY.

Эти классы ответственны исключительно за то, чтобы "передвинуть" объект на новую позицию. При этом вычисление этой новой позиции происходит в классах PlanetMovementCalc и MoveToTargetCalc, которые реализуют интерфейс IMoveCalculator. И вот на этом месте начинаются проблемы:

Для расчёта новой позиции MoveToTargetCalc нужны два вектора и скорость, а PlanetMovementCalcinput в виде значения типа float, радиус орбиты и скорость. Как вы понимаете, если я добавлю оба метода для расчёта новой позиции в IMoveCalculator, то мне придётся реализовать метод, предназначенный для MoveToTargetCalc, в PlanetMovementCalc и наоборот. Что PlanetMovementCalc, что MoveToTargetCalc — это, понятное дело, не нужно. Если реализовать методы пустыми, то это будет нарушением принципа Лисков, а если реализовать методы по-нормальному, то это будет просто куча лишнего кода, который не будет использоваться.

Вопрос: что же делать? Вообще убрать интерфейс из проекта, так как PlanetMovementCalc и MoveToTargetCalc по задумке и не должны быть взаимозаменяемыми? Или есть смысл в использовании интерфейсов? Если да, то как их использовать правильно?

(Извиняюсь за глупый вопрос, просто у меня мало опыта, и сам я "докумекать" не могу)


Ответы (1 шт):

Автор решения: Yaroslav

Архитектура, как не странно начинается с нейминга! Если твоя архитектура начинается к класса GameManager, любой скажет, что твоя архитектура ShinimaHuina, даже не уточняя, чем именно этот класс занимается.

abstract, private, public и т.д. это модификаторы доступа, а не члены имён! Manager или System это слова паразиты в 99% случаях, когда человек не может сформулировать, чем именно сущность занимается. Аббревиатуры абсолютное зло, но сокращения допустимы, как общепринятые в конкретных областях, как например Str, Agi и Int в видеоиграх, хотя когда в один случаях слово сокращают, а в других нет, это грязь и беспорядок.


Кроме того, что у AbstractMovementSystem есть два поля, ты ни слова не написал, о его бизнес процессах. Почему называется AbstractMovementSystem? Потому, что абстрактное хрен знает что, но что-то связанное с движением! Если разные сущности объединены только именами свойств и методов, то это их объединяет общий интерфейс, потому что никакой логики они не наследуют, как юнит и разрушаемая декорация, которые оба IDamagable, но получаемый урон, каждый обрабатывает по своему. По двум свойствам Speed и MaxSpeed, можно разве что выделить интерфейс ISpeed, хотя дико странно, что планеты у тебя двигаются с переменной скоростью и имеют потолок скорости.

В этих случаях, я честно именовал класс аля... XXX и уже реализовав нужный мне функционал, давал имя отражающее этот функционал в контексте названий методов или разделял сущность на несколько в виду множественной ответственности.


Я не особо понял, зачем логика движения выделена в классы, почему движение планеты описано не к кассе планеты? В некоторых случаях мы выносим логику из классов, как например в паттерне State, потому что оно меняется, но тут это зачем?

Если бы все тела в твоей солнечной системе двигались согласно Ньютоновской механике, был бы класс типа CelestialBody, от которого наследовались все объекты и обработкой этих тел занимался бы какой-нибудь NewtonPhysics. У тебя это не так, реальная физика игре не нужна, звезда не двигается, планеты перемещаются строго по кругу а корабли летят куда хотят, у них буквально нет ни хрена общего между собой.


Твоя проблема не в интерфейсах и вообще не в абстракции, а в том, что ты не можешь сформулировать, чё те надо то... и чё делать то... и просто бежишь впереди паровоза, что бы бежать и не думать, потому что думать это больно!

→ Ссылка