Godot — движок, в основе которого лежит объектно-ориентированная архитектура. Но ООП в Godot устроено не так, как в классическом программировании на Java или C#. Здесь классы не парят в абстракции — они буквально живут в сцене, а наследование, композиция и сигналы работают вместе, чтобы строить гибкую и выразительную игровую логику. В этой статье мы максимально подробно разберём модель ООП в Godot: что она собой представляет, как она устроена и как использовать её эффективно.

Если вы хотите понимать Godot «как движок мыслит», то без этой статьи не обойтись.

Что такое ООП в контексте Godot

Объектно-ориентированная концепция в Godot опирается на три ключевые идеи:

  • Каждая нода — объект.
  • Каждый .gd-файл — класс.
  • Каждая сцена — дерево объектов.

Поэтому GDScript и сцены Godot образуют целостный объектный мир: объекты наследуют поведение, ноды взаимодействуют друг с другом, а сцены позволяют собирать сложные структуры как из блоков LEGO.

Класс в GDScript = Скрипт + Нода

Класс в GDScript создаётся в момент, когда вы пишете скрипт:

extends Node2D

var speed := 200

func move_forward(delta):
    position.x += speed * delta

Этот скрипт:

  • является классом;
  • расширяет Node2D (родительский класс);
  • создаёт компонент поведения для ноды.

Важный момент: один и тот же класс можно использовать либо как компонент ноды, либо как отдельный объект, если создать его вручную через new().

Фундаментальная мысль: класс в Godot — это способ расширить поведение ноды сцены. Он не бывает «пустым», он всегда привязан к какому-то уровню дерева объектов.

class_name — именованные классы

По умолчанию ваш класс анонимный. Но если вы хотите использовать его как полноценный тип — присвойте ему имя:

class_name Enemy
extends CharacterBody2D

var health := 100

Теперь:

  • класс появляется в списке типов Godot;
  • можно создавать его через Enemy.new();
  • его можно использовать как тип в аннотациях (например: var target: Enemy).

Наследование: расширение поведения

Наследование в Godot — прямое и понятное. Вы делаете новый класс на основе существующего:

class_name CharacterBase
extends CharacterBody2D

var speed := 120
var health := 100

func move(direction: Vector2, delta: float):
    velocity = direction * speed
    move_and_slide()

И дочерний класс:

class_name Enemy
extends CharacterBase

func _process(delta):
    move(Vector2.LEFT, delta)

Дочерний класс может:

  • добавлять новые свойства;
  • переопределять функции;
  • использовать всё, что было в родителе.

Когда использовать наследование

Оно уместно, когда:

  • классы имеют одинаковую природу (все — персонажи);
  • поведение базовое, а различия — в деталях;
  • вы хотите избежать дублирования логики.

Например, Player и Enemy оба могут наследоваться от CharacterBase.

Когда не использовать наследование

Наследование в Godot легко приводит к слишком глубоким цепочкам.

Рекомендация: не делайте более 2–3 уровней наследования. Дальше лучше перейти на композицию.

super: вызов родительских методов

Если нужно расширить, а не заменить поведение родителя:

func _ready():
    super._ready()
    print("Enemy готов к бою")

Это полезно, когда базовый класс уже делает часть работы, а дочернему классу нужно добавить к ней что-то своё.

Композиция: главный принцип Godot

📢 Подписывайтесь на наш Telegram-канал.

Там вы найдете анонсы обучающих статей и видео, готовый код для ваших проектов и увлекательные курсы. Ничего лишнего — только практика, вдохновение и развитие.

👉 https://t.me/codelab_channel

В Godot композиция важнее наследования.

Композиция = объект собирается из нескольких самостоятельных компонентов.

Пример:

  • HealthComponent.gd — здоровье;
  • AttackComponent.gd — атака;
  • AIComponent.gd — интеллект;
  • LootComponent.gd — выпадение предметов.

В итоге враг может состоять так:

Enemy
├── HealthComponent
├── AttackComponent
├── AIComponent
└── Sprite2D

Плюсы:

  • гибко комбинируется;
  • легко заменить один компонент;
  • легко тестировать;
  • нет огромных классов.

Композиция — лучший вариант для больших проектов. Она позволяет создавать разные сущности из общих блоков.

Сигналы: события между объектами

Сигналы — элемент ООП-модели Godot. Это способ разъединить объекты: один сообщает о событии, другие реагируют.

Создание сигнала

signal died

Вызов сигнала

func take_damage(amount):
    health -= amount
    if health <= 0:
        emit_signal("died")

Подключение сигнала

func _ready():
    connect("died", self, "_on_died")

func _on_died():
    queue_free()

Зачем нужны сигналы

  • объект не обязан знать ВСЁ о другом объекте;
  • код становится гибче;
  • сцены проще поддерживать.

Пример: UI слушает события игрока, но не знает *как* работает игрок.

Взаимодействие нод в сцене

Ноды в Godot взаимодействуют через дерево сцены. Это важная часть ООП-модели движка.

Два стандартных способа

Короткие пути через $

$Sprite2D.flip_h = true

2. Полный путь через get_node()

var enemy = get_node("Enemies/Enemy1")
enemy.take_damage(20)

Используйте onready для безопасного получения ноды:

onready var ui := get_node("../UI")

Передача данных между объектами

Есть пять рабочих способов:

  • Передать ссылку → надёжно.
  • Использовать сигналы → модульно.
  • Использовать автозагрузку → глобально.
  • Хранить зависимости в родительской ноде → структурно.
  • Инициализировать объект параметрами после создания → гибко.

Пример параметризации:

var bullet = bullet_scene.instantiate()
bullet.damage = 25
bullet.direction = Vector2.RIGHT
add_child(bullet)

Встроенные классы Godot и их роль в ООП

Godot предлагает богатую иерархию классов:

  • Node — базовый объект;
  • Node2D / Node3D — позиция;
  • CharacterBody2D — движение с физикой;
  • RigidBody2D — физика высокого уровня;
  • Area2D — триггеры;
  • Sprite2D / AnimatedSprite2D — визуал;
  • Timer — таймеры;
  • AI NavigationAgent2D — навигация.

Каждый из этих классов можно расширить через наследование или использовать как компонент при композиции.

Переопределение методов

Переопределяйте методы, когда хотите изменить поведение:

func _process(delta):
    super._process(delta)
    patrol()

Это позволяет добавлять новую логику, не ломая базовый класс.

Главная философия ООП в Godot

Её можно выразить в одном предложении:

  • Ноды = объекты
  • Сцены = классы объектов
  • Скрипты = поведение
  • Сигналы = связь между ними

Это сильно отличается от привычных моделей ООП, но на практике работает намного гибче для разработки игр.

Итоги статьи

Мы глубоко разобрали объектно-ориентированную модель Godot. Теперь вы понимаете:

  • как работает система классов GDScript;
  • как использовать class_name правильно;
  • когда применять наследование, а когда — композицию;
  • как строить архитектуру через сигналы;
  • как ноды взаимодействуют внутри сцены;
  • как передавать данные между объектами;
  • как расширять встроенные классы движка.

Умение грамотно применять эти инструменты — шаг от «просто работающего кода» к архитектуре, которую легко поддерживать и развивать.

Комментарии

0

Без регистрации и смс