Вместо того чтобы раздувать основной класс (Godot Node) до "Божественного объекта", мы разделяем его на ответственности. Основной класс остается "Контроллером/Хранилищем данных", а вся логика выносится в специализированные Mixin-классы.
Все миксины наследуются от Mixin.gd (на базе RefCounted). Он хранит ссылку на родителя для доступа к его данным и методам.
class_name Mixin
extends RefCounted
var parent: Node
func _init(_parent: Node) -> void:
parent = _parent
post_init.call_deferred()
func post_init() -> void:
pass- Определение ответственности: Выдели логически связанный блок (Физика, Спавнер, Отрисовка, AI, Логика входа).
- Создание файла: Называй файл по шаблону
ParentClass_Responsibility.gd. - Перенос констант: Если константа используется только внутри этой ответственности, она должна переехать в миксин.
- Перенос приватных переменных: Если _приватная переменная используется только внутри этой ответственности, она должна переехать в миксин.
- Доступ к данным: Миксин обращается к переменным, сигналам и другим миксинам родителя через префикс
parent.. - Делегирование: В основном классе создается экземпляр миксина, и вызовы из
_process,_physics_processили_inputперенаправляются в него.
class_name SnakeMover
extends Node
# Данные остаются здесь
@export var speed: float = 100.0
var _followers: Array[PathFollow2D] = []
# Инициализация миксинов
var physics := SnakeMover_Physics.new(self)
var spawner := SnakeMover_Spawner.new(self)
func _physics_process(delta: float) -> void:
# Только делегирование
physics.step(delta)
func spawn() -> void:
spawner.run()class_name SnakeMover_Physics
extends Mixin
const FRICTION: float = 0.9 # Локальная константа, перенесенная из родителя
func step(delta: float) -> void:
for f in parent._followers:
f.progress += parent.speed * delta * FRICTION- Приватные переменные:
_vars, которые нужны нескольким миксинам, остаются в родителе. - Константы: Перенесены ли специфичные для логики константы в миксин?
- Делегирование: Есть ли в родителе вызов метода миксина (например, в
_ready,_processили по событию)? - Сигналы: Все ли вызовы сигналов заменены на
parent.signal_name.emit()? - Связи миксинов: Если миксин А должен вызвать метод миксина Б, используй
parent.mixin_b.method(). - Стиль: Используются табы для отступов и явная типизация.
- Чистота: Основной файл сокращается в несколько раз.
- Навигация: Легко найти нужную логику по названию файла миксина.
- Изоляция: Изменение физики не может случайно затронуть отрисовку или спавн.